I usually have trouble serializing/deserializing json when I first learn a
staticly typed language. I had the same experience with C# and in Haskell. Luckily,
there’s a lot of resources and it’s easy to understand. This time I’m learning
Ocaml/Bucklescript and I’m encoutering the same thing. Good thing
bucklescript’s standard library provides Js.Json.
JSON Encoding
Creating a simple json object.
let jsonPerson =
[ ("firstName", Js.Json.string "John")
; ("lastName", Js.Json.string "Doe")
]
|> Js.Dict.fromList
|> Js.Json.object_Creating json from a record. First, create the record type.
type person =
{ firstName : string
; lastName : string
}Then create a record value.
let personRec =
{ firstName = "John"
; lastName = "Doe"
}Now, a function that will serialize the record.
let jsonPerson (p : person) =
[ ("firstName", Js.Json.string p.firstName)
; ("lastName", Js.Json.string p.lastName)
]
|> Js.Dict.fromList
|> Js.Json.object_To see the output in the console.
let _ =
personRec
|> jsonPerson
|> Js.logJSON Decoding
I’m gonna do the other way around in this next section. Deserializing
json! When I get a json object I will transform it
into personRec record.
Let’s say this is the json object I get.
{ firstName : "John"
, lastName : "Doe"
}First, I need to define a record since there’s no such thing as anonymous records in Ocaml.
type person =
{ firstName : string
; lastName : string
} [@@bs.deriving abstract]I’ll use [@@bs.deriving abstract] decoractor for maninpulating
json since Ocaml’s data representation is not really the same
with javascript, and also it will give me convenience functions to access the
fields.
I’ll create a utility function to help me extract json.
let extractField field jsonDict =
let open Belt_Option in
let id a = a in
flatMap
(Js.Dict.get jsonDict field)
Js.Json.decodeString
|> (function o -> mapWithDefault o "" id)This will be my main decoding function
let jsonToPerson json =
match Js.Json.decodeObject json with
| Some j ->
personRec
~firstName:(extractField "firstName" j)
~lastName:(extractField "lastName" j)
| None ->
personRec
~firstName:""
~lastName:""To simulate a json object I’ll make jsonPerosn.
let jsonPerson =
[ ("firstName", Js.Json.string "John")
; ("lastName", Js.Json.string "Doe")
]
|> Js.Dict.fromList
|> Js.Json.object_To view the output
let _ =
person
|> jsonToPerson
|> Js.logUsing bs-json
JSON Encoding
I’ll encode a record using bs-json to turn it into a json object.
First, I’ll create the record type.
type person =
{ firstName : string
; lastName : string
}Then, the record itself.
let personRec =
{ firstName = "John"
; lastName = "Doe"
}Next, will be the function to create the json object from the
record
let jsonPerson (p : person) =
let open Json.Encode in
object_
[ ("firstName", string p.firstName)
; ("lastName", string p.lastName)
]To view the output in the console.
let _ =
personRec
|> jsonPerson
|> Js.logJSON Decoding
I’m expecting the same json from above.
{ firstName : "John"
, lastName : "Doe"
}Define the person record.
type person =
{ firstName : string
; lastName : string
} [@@bs.deriving abstract]Then, the function to transform the record to a json object.
let jsonToPerson json =
let open Json.Decode in
person
~firstName:(json |> (field "firstName" string))
~lastName:(json |> (field "lastName" string))To see the output in the console
let _ =
jsonPerson
|> jsonToPerson
|> Js.log