【问题标题】:Convert JSON field to ReasonML variant将 JSON 字段转换为 ReasonML 变体
【发布时间】:2018-06-19 19:39:58
【问题描述】:

我有一个 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 进行匹配,String 是我的periodVariant 的一部分,但我不知道如何实现我想要什么。

【问题讨论】:

    标签: json reason bucklescript bs-json


    【解决方案1】:

    这就是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))
      ));
    

    【讨论】:

    • 嗯,这似乎不起作用...我在period |> map... 行上得到The value period can't be found
    • period 是上面定义的函数。如果您没有定义它,或者可能在名称中打错字,那么您肯定会收到该错误。
    • 这比我的回答优雅多了。谢谢!
    【解决方案2】:

    我看到您正在使用 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 一起编译。我不确定这是否是惯用的方式!

    【讨论】:

    • 只是想说我会在下面推荐@glennsl的答案!
    猜你喜欢
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    相关资源
    最近更新 更多