This module provides a way to decode JSON objects while making sure that all fields are handled. The interface works similar to json-decode-pipeline. For example,
import Json.Decode as D exposing (Decoder)
import DecodeComplete exposing (..)
type alias User =
{ name : String
, age : Int
}
userDecoder : Decoder User
userDecoder =
object User
|> required "name" D.string
|> required "age" D.int
|> discard "email"
|> complete
decodes JSON objects that have precisely the fields name
, age
, and email
and turns it into a User
record, discarding the email address.
The general usage is as follows: Start decoding the object with object f
, where f
is the function being called with the results. Then decode the individual fields with require
, discard
, optional
, discardOptional
. At the end, turn turn the ObjectDecoder
into a normal Decoder
by calling complete
(or discardRest
or rest
or restValues
).
A decoder for JSON objects that makes sure that all fields in the JSON are handled
object : a -> ObjectDecoder a
Start decoding a JSON object.
required : String -> Json.Decode.Decoder a -> ObjectDecoder (a -> b) -> ObjectDecoder b
Decode the field given by the String
parameter using the given (regular) Decoder
. If the field is missing, the decoder fails.
optional : String -> Json.Decode.Decoder a -> a -> ObjectDecoder (a -> b) -> ObjectDecoder b
Decode the field given by the String
parameter using the given (regular) Decoder
. If the field is missing or the decoder fails, use the provided default value instead.
discard : String -> ObjectDecoder a -> ObjectDecoder a
Require that a field is present, but discard its value.
discardOptional : String -> ObjectDecoder a -> ObjectDecoder a
Discard the value of a field (thus marking it as handled), but simply ignore if its not there.
hardcoded : a -> ObjectDecoder (a -> b) -> ObjectDecoder b
Don’t look at the JSON, simply use the given value.
complete : ObjectDecoder a -> Json.Decode.Decoder a
Close the ObjectDecoder
, turning it into a regular Decoder
. If unhandled fields in the JSON remain, this decoder will fail.
discardRest : ObjectDecoder a -> Json.Decode.Decoder a
Turn the ObjectDecoder
into a regular Decoder
. Ignore if fields remain unhandled.
This might be useful if you only want the check that all fields are handled to occur during development. You can use complete
in development and change it into discardRest
without having to change anything else.
rest : Json.Decode.Decoder a -> ObjectDecoder (Dict String a -> b) -> Json.Decode.Decoder b
Decode the remaining fields uniformly with the given Decoder
, pass the dictionary of the results and close the ObjectDecoder
turning it into a regular Decoder
.
restValues : ObjectDecoder (Dict String Json.Decode.Value -> b) -> Json.Decode.Decoder b
Finish up the ObjectDecoder
, turning it into a regular decoder. Pass a dictionary of the unhandled fields (as Decode.Value
values).
andThen : (a -> ObjectDecoder b) -> ObjectDecoder a -> ObjectDecoder b
Decide how to proceed based on earlier fields. This can be useful if the JSON represents a sum type or has different versions. For example
userDecoder : Decoder ( String, Int )
userDecoder =
(object identity
|> required "version" D.int
)
|> andThen
(\version ->
case version of
0 ->
object Tuple.pair
|> required "name" D.string
|> required "age" D.int
1 ->
object Tuple.pair
|> required "fullName" D.string
|> required "age" D.int
|> discard "email"
_ ->
fail "unsupported version"
)
|> complete
first decodes the version
field. If it is 0
, the JSON needs to have (exactly) the fields name
and age
. If the version is 1
, the JSON needs the fields fullName
, age
and email
instead. If the version is anything else, fail.
fail : String -> ObjectDecoder a
An ObjectDecoder
that always fails. Can be useful in combination with andThen
.