使用 hl_yaml 反序列化和后处理 YAML 数据

任务

数据格式 / YAML / 反序列化和后处理 YAML 数据

反序列化一个结构没有直接映射到 OCaml 类型 的 YAML 文件。

使用的 Opam 包

代码

此 YAML 字符串包含一个配料列表,其中配料以 YAML 对象形式表示,键表示名称,值表示数量。

let yaml = {|
french name: pâte sucrée
ingredients:
- flour: 250
- butter: 100
- sugar: 100
- egg: 50
- salt: 5
steps:
- soften butter
- add sugar
- add egg and salt
- add flour
|}

[@@deriving of_yojson] 属性使 ppx_deriving_yojson 库生成函数 ingredient_of_yojson : Yojson.Safe.t -> (ingredient, string) result

type ingredient = {
  name: string;
  weight: int;
} [@@deriving of_yojson]

[@@deriving of_yojson] 属性使 ppx_deriving_yojson 库生成函数 recipe_of_yojson : Yojson.Safe.t -> (ingredient, string) result

type recipe = {
  name: string; [@key "french name"]
  ingredients: ingredient list;
  steps: string list;
} [@@deriving of_yojson]

由于 YAML 文件的结构与 recipe 类型不完全匹配,我们 (1) 将 YAML 文件解析为 Yojson.Safe.t 表示形式,然后 (2) 修改 Yojson.Safe.t 值以更改结构以匹配 recipe 类型,这样我们就可以使用 recipe_of_yojson 函数。

函数 add_keysat_ingredients 执行此后处理。

let add_keys = function
  | `Assoc [(name, `Int weight)] ->
      `Assoc [
        ("name", `String name);
        ("weight", `Int weight);
      ]
  | v -> v

let at_ingredients f = function
  | `Assoc [
      ("french name", `String name);
      ("ingredients", `List ingredients);
      ("steps", `List steps)
    ] -> `Assoc [
      ("french name", `String name);
      ("ingredients",
        Yojson.Safe.Util.map f (`List ingredients));
      ("steps", `List steps);
    ]
  | v -> v

解析、后处理并将 YAML 字符串转换为 recipe 类型的 OCaml 值。

let pate_sucree =
  let of_yojson json =
    json
    |> at_ingredients add_keys
    |> recipe_of_yojson in
  yaml
  |> Hl_yaml.Unix.parse ~of_yojson

食谱无效?注释不清楚或已过期?

创建问题 或者 为这个食谱贡献

此任务的其他食谱