Skip to content

Commit

Permalink
Deserialise and post-process recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
Cuihtlauac ALVARADO authored and tmattio committed Jun 14, 2024
1 parent 66641c6 commit 4f3d30d
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
72 changes: 72 additions & 0 deletions data/cookbook/deserialise-post-process-from-yaml/00-yaml.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
packages:
- name: yaml
tested_version: 3.2.0
used_libraries:
- yaml
- name: ppx_deriving_yaml
tested_version: 0.2.2
used_libraries:
- ppx_deriving_yaml
---
(* The syntax `{| ... |}` is a quoted string. *)
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
|}

(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function
``ingredient_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result``
If both serialising and deserialising are needed, replace `of_yaml` by `yaml`. *)
type ingredient = {
name: string;
weight: int;
} [@@deriving of_yaml]

(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function
``recipe_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result``. *)
type recipe = {
name: string; [@key "french name"]
ingredients: ingredient list;
steps: string list;
} [@@deriving of_yaml]

(* Post-processing is needed before using `recipe_of_yaml`.
This what function `add_keys` and `at_ingredients` do. *)
let add_keys : Yaml.value -> Yaml.value = function
| `O [(name, `Float weight)] ->
`O [
("name", `String name);
("weight", `Float weight);
]
| v -> v

let at_ingredients f : Yaml.value -> Yaml.value = function
| `O [
("french name", `String name);
("ingredients", `A ingredients);
("steps", `A steps)
] -> `O [
("french name", `String name);
("ingredients", Yaml.Util.map_exn f (`A ingredients));
("steps", `A steps);
]
| v -> v

(* Parsing, post-processing and conversion into recordd are chained. *)
let pate_sucree =
yaml
|> Yaml.of_string
|> Result.map (at_ingredients add_keys)
|> fun yaml -> Result.bind yaml recipe_of_yaml

73 changes: 73 additions & 0 deletions data/cookbook/deserialise-post-process-from-yaml/01-hl_yaml.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
packages:
- name: hl_yaml
tested_version: 1.0.0
used_libraries:
- hl_yaml
- name: ppx_deriving_yojson
tested_version: 3.7.0
used_libraries:
- ppx_deriving_yojson
---
(* The syntax `{| ... |}` is a quoted string. *)
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
|}

(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function
`ingredient_of_yojson : Yojson.Safe.t -> (ingredient, string) result`.
If both serialising and deserialising are needed, replace `of_yojson` by `yojson`. *)
type ingredient = {
name: string;
weight: int;
} [@@deriving of_yojson]

(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function
``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]

(* Post-processing is needed before using `recipe_of_yojson`.
This what function `add_keys` and `at_ingredients` do. *)
let add_keys : Yojson.Safe.t -> Yojson.Safe.t = function
| `Assoc [(name, `Int weight)] ->
`Assoc [
("name", `String name);
("weight", `Int weight);
]
| v -> v

let at_ingredients f : Yojson.Safe.t -> Yojson.Safe.t = 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

(* Parsing receives post-processing and conversion into record as an argument. *)
let pate_sucree =
let of_yojson json =
json
|> at_ingredients add_keys
|> recipe_of_yojson in
yaml
|> Hl_yaml.Unix.parse ~of_yojson

0 comments on commit 4f3d30d

Please sign in to comment.