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 =
string
{ firstName : string
; lastName : }
Then create a record value.
let personRec =
"John"
{ firstName = "Doe"
; lastName = }
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 log |> Js.
JSON 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.
"John"
{ firstName : "Doe"
, lastName : }
First, I need to define a record since there’s no such thing as anonymous records in Ocaml.
type person =
string
{ firstName : string
; lastName : } [@@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.decodeStringfunction o -> mapWithDefault o "" id) |> (
This will be my main decoding function
let jsonToPerson json =
match Js.Json.decodeObject json with
Some j ->
|
personRec"firstName" j)
~firstName:(extractField "lastName" j)
~lastName:(extractField 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 log |> Js.
Using 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 =
string
{ firstName : string
; lastName : }
Then, the record itself.
let personRec =
"John"
{ firstName = "Doe"
; lastName = }
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 log |> Js.
JSON Decoding
I’m expecting the same json
from above.
"John"
{ firstName : "Doe"
, lastName : }
Define the person
record.
type person =
string
{ firstName : string
; lastName : } [@@bs.deriving abstract]
Then, the function to transform the record to a json
object.
let jsonToPerson json =
let open Json.Decode in
person"firstName" string))
~firstName:(json |> (field "lastName" string)) ~lastName:(json |> (field
To see the output in the console
let _ =
jsonPerson
|> jsonToPersonlog |> Js.