Преобразовать поле JSON в вариант ReasonML
У меня есть структура JSON, которая содержит поле period
это может быть либо объект, либо строка. У меня уже есть готовый вариант в моем коде, и он работает нормально:
type period = {
start: string,
end_: string,
};
type periodVariant =
| String(string)
| Period(period);
Проблема в том, что я пытаюсь привести входной JSON к типу варианта: я просто не знаю, как это сделать. Вот как выглядит моя попытка:
let periodVariantDecode = (json: Js.Json.t): periodVariant => {
switch(json) {
| String(string) => String(Json.Decode.string(string))
| period => Period(Json.Decode.{
start: period |> field("start", string),
end_: period |> field("end", string),
})
};
};
Теперь, конечно, это не работает, потому что я пытаюсь сопоставить что-то, что по-прежнему типа Js.Json.t
против String
которая является частью моего periodVariant
, но я не знаю, как добиться того, чего я хочу.
2 ответа
Это то, что either
для. Вместе с map
удобно "поднять" существующий декодер на ваш тип варианта.
type period = {
start: string,
end_: string,
};
type periodVariant =
| String(string)
| Period(period);
let period = json =>
Json.Decode.{
start: json |> field("start", string),
end_: json |> field("end", string),
};
let periodVariantDecode =
Json.Decode.(either(
period |> map(p => Period(p)),
string |> map(s => String(s))
));
Я вижу, вы используете bs-json, поэтому один из способов сделать это - воспользоваться тем, что Json.Decode.optional
возвращается None
если декодирование не удается. Для вашего примера:
type period = {
start: string,
end_: string,
};
type periodVariant =
| String(string)
| Period(period);
let periodVariantDecode = json => {
let periodString = json |> Json.Decode.(optional(string));
switch (periodString) {
| Some(periodString) => String(periodString)
| None =>
let periodObj =
Json.Decode.{
start: json |> field("start", string),
end_: json |> field("end", string),
};
Period(periodObj);
};
};
Это должно скомпилировать с periodVariantDecode
быть типом Js.Json.t => periodVariant
, Я не уверен, если это идиоматический способ пойти, хотя!