Creating json for optional fields

I have a record with optional field and I want to serialize it in json with the code below

type person = {name: string, middleName: option string}
let personList = [{name="Abhishek"}; {name="someone", middleName="else"}] in 
let json = personList 
|> `List (
       List.map( fun x -> `Assoc [
         ("name", `String x.name); 
         ("middle-name", `String x.middleName)])) in 
json 
|> Yojson.Basic.pretty_to_string 
|> print_endline

but it doesn’t work because the data type doesn’t match.

In the type person the field middleName is not an optional field. It is a mandatory field which contains an optional value (either None or Some [string])

From that, you can guess that you can’t directly read value like you did in x.middleName. You have to handle the case where the value is missing, and fetch the value from the optional.

In order to do this, you can either to pattern matching, or use Option.value

2 Likes

Oh thanks. yes that makes sense. So how do I make the field itself optional in the json (I understand from your explanation that in the record it will always be there). So if middleName is None. the json looks like {"name":"abhishek"}; but if middleName is Some then the json contains the middleName.

If you use e.g. ppx_deriving_yojson it has an option to not output fields which have None value: GitHub - ocaml-ppx/ppx_deriving_yojson: A Yojson codec generator for OCaml.

EDIT: or if you want to do it by hand, then:

let person_to_json { name; middle_name } =
  let fields = ["name", name] in
  `Assoc (match middle_name with
    | Some mn -> ("middle-name", mn) :: fields
    | None -> fields)
1 Like

List.filter_map can also help with constructing the list for `Assoc.

In order to chain may values like that, I would have used Option.fold:

let person_to_json : person -> json = fun { name; middle_name } ->
  let fields = ["name", name ] in
  let fields = Option.fold middle_name ~none:field ~some:(fun v -> ("middle_name", v)::fields) in
  fields
1 Like

I love this code. didn’t realize you can write option fold with named parameters. I like it more than writing if else. :slight_smile:

If we have to chain ‘many’ values then we might as well use the PPX and greatly simplify the code :slightly_smiling_face:

You are right @yawaramin My long term goal is to use PPX based derivation. I am trying to figure out how to install GitHub - janestreet/ppx_yojson_conv: [@@deriving] plugin to generate Yojson conversion functions (I think this PPX is more well maintained than the one you shared).