Json
Efficient JSON handling This module has four aspects to it:
parse
and parseOrRaise
will both (try to) parse a JSON string into a JSON data structure (Js.Json.t
), but behaves differently when encountering a parse error. parseOrRaise
will raise a ParseError
, while parse
will return a Js.Json.t result
indicating whether or not the parsing succeeded. There's not much more to it: string
in, Js.Json.t
out. The parsed result, and encoded JSON data structure, then needs to be decoded to actually be usable. See Decoding
below.
Stringification is the exact reverse of parsing. stringify
and stringifyAny
both technically do the same thing, but where stringifyAny
will take any value and try to do its best with it, retuning a string option
, stringify
on the other hand uses the type system to guarantee success, but requires that the data has been encoded in a JSON data structure first. See Encoding
below.
Encoding creates a JSON data structure which can stringified directly with stringify
or passed to other APIs requiring a typed JSON data structure. Or you could just go straight to decoding it again, if that's your thing. Encoding functions are in the Encode
module.
Decoding is a more complex process, due to the highly dynamic nature of JSON data structures. The Decode
module provides decoder combinators that can be combined to create complex composite decoders for any _known_ JSON data structure. It allows for custom decoders to produce user-defined types.
@example
(* Parsing a JSON string using Json.parse *)
let arrayOfInts str
match Json.parse str with
| Some value ->
match Json.Decode.(array int value)
| Ok arr -> arr
| Error _ -> []
| None -> failWith "Unable to parse JSON"
(* prints `[3, 2, 1]` *)
let _ = Js.log (arrayOfInts "[1, 2, 3]" |> Js.Array.reverse)
@example
(* Stringifying a value using Json.stringify *)
(* prints `null` *)
let _ =
Json.stringify (Encode.int 42)
|> Js.log
@example
(* Encoding a JSON data structure using Json.Encode *)
(* prints ["foo", "bar"] *)
let _ =
[| "foo", "bar" |]
|> Json.Encode.stringArray
|> Json.stringify
|> Js.log
(* prints ["foo", "bar"] *)
let _ =
[| "foo", "bar" |]
|> Js.Array.map Encode.int
|> Json.Encode.jsonArray
|> Json.stringify
|> Js.log
@example
(* Decoding a fixed JSON data structure using Json.Decode *)
let mapJsonObjectString f decoder encoder str =
match Json.parse str with
| Ok json ->
match Json.Decode.(dict decoder json) with
| Ok dict ->
dict |> Js.Dict.map f
|> Js.Dict.map encoder
|> Json.Encode.dict
|> Json.stringify
| Error _ -> []
| Error _ -> []
let sum ns =
Array.fold_left (+) 0
(* prints `{ "foo": 6, "bar": 24 }` *)
let _ =
Js.log (
mapJsonObjectString sun Json.Decode.(array int) Json.Encode.int {|
{
"foo": [1, 2, 3],
"bar": [9, 8, 7]
}
|}
)
module Decode : sig ... end
Provides a set of low level combinator primitives to decode Js.Json.t data structures A decoder combinator will return the decoded value if successful, or raise a DecodeError of string
if unsuccessful, where the string argument contains the error message. Decoders are designed to be combined to produce more complex decoders that can decode arbitrary data structures, though the emphasis for this library is for it to be possible to decode any given data structure, not necessarily for it to be convenient. For convenience you should look towards opinionated third-party libraries.
module Encode : sig ... end
Provides functions for encoding a JSON data structure
parse s
returns Some json
if s is a valid json string, None
otherwise
parse s
returns a Js.Json.t
if s is a valid json string, raises ParseError
otherwise