webbhuset / elm-json-decode / Json.Decode.Field

Decode JSON objects

Since JSON values are not known until runtime there is no way of checking them at compile time. This means that there is a possibility a decoding operation can not be successfully completed.

In that case there are two possible solutions:

  1. Fail the whole decoding operation.
  2. Deal with the missing value situation, either by defaulting to some value or by using a Maybe value

In this module these two options are represented by require, optional, and attempt.

require : String -> Json.Decode.Decoder a -> (a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode required fields.

Example:

import Json.Decode as Decode exposing (Decoder)

user : Decoder User
user =
    require "id" Decode.int <| \id ->
    require "name" Decode.string <| \name ->

    Decode.succeed
        { id = id
        , name = name
        }

In this example the decoder will fail if:

requireAt : List String -> Json.Decode.Decoder a -> (a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode required nested fields. Works the same as require but on nested fieds.

import Json.Decode as Decode exposing (Decoder)

blogPost : Decoder BlogPost
blogPost =
    require "id" Decode.int <| \id ->
    require "title" Decode.string <| \title ->
    requireAt ["author", "name"] Decode.string <| \authorName ->

    Decode.succeed
        { id = id
        , title = title
        , author = authorName
        }

optional : String -> Json.Decode.Decoder a -> (Maybe a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode optional fields.

If the decode succeeds you get a Just value. If the field is missing you get a Nothing.

Example:

import Json.Decode as Decode exposing (Decoder)

name : Decoder Name
name =
    require "first" Decode.string <| \first ->
    optional "middle" Decode.string <| \maybeMiddle ->
    require "last" Decode.string <| \last ->

    Decode.succeed
        { first = first
        , middle = Maybe.withDefault "" middle
        , last = last
        }

The outcomes of this example are:

Note that optional is not the same as nullable. If a field must exist but can be null, use require and Decode.nullable instead:

require "field" (Decode.nullable Decode.string) <| \field ->

If a field is both optional and nullable attempt is a better option than using optional with Decode.nullable, as attempt gives you a Maybe a compared to the Maybe (Maybe a) that optional with nullable would give:

attempt "field" Decode.string <| \maybeField ->

optionalAt : List String -> Json.Decode.Decoder a -> (Maybe a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode optional nested fields. Works the same was as optional but on nested fields.

attempt : String -> Json.Decode.Decoder a -> (Maybe a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode fields that may fail.

Always decodes to a Maybe value and never fails.

Example:

import Json.Decode as Decode exposing (Decoder)

person : Decoder Person
person =
    require "name" Decode.string <| \name ->
    attempt "weight" Decode.int <| \maybeWeight ->

    Decode.succeed
        { name = name
        , weight = maybeWeight
        }

In this example the maybeWeight value will be Nothing if:

In this case there is no difference between a field being null or missing.

attemptAt : List String -> Json.Decode.Decoder a -> (Maybe a -> Json.Decode.Decoder b) -> Json.Decode.Decoder b

Decode nested fields that may fail. Works the same way as attempt but on nested fields.