Use the (|>)
operator to build JSON decoders.
required : String -> Json.Decode.Decoder a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Decode a required field.
import Json.Decode as Decode exposing (Decoder, int, string)
import Json.Decode.Pipeline exposing (required)
type alias User =
{ id : Int
, name : String
, email : String
}
userDecoder : Decoder User
userDecoder =
Decode.succeed User
|> required "id" int
|> required "name" string
|> required "email" string
result : Result String User
result =
Decode.decodeString
userDecoder
"""
{"id": 123, "email": "sam@example.com", "name": "Sam"}
"""
-- Ok { id = 123, name = "Sam", email = "sam@example.com" }
requiredAt : List String -> Json.Decode.Decoder a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Decode a required nested field.
optional : String -> Json.Decode.Decoder a -> a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Decode a field that may be missing or have a null value. If the field is
missing, then it decodes as the fallback
value. If the field is present,
then valDecoder
is used to decode its value. If valDecoder
fails on a
null
value, then the fallback
is used as if the field were missing
entirely.
import Json.Decode as Decode exposing (Decoder, int, null, oneOf, string)
import Json.Decode.Pipeline exposing (optional, required)
type alias User =
{ id : Int
, name : String
, email : String
}
userDecoder : Decoder User
userDecoder =
Decode.succeed User
|> required "id" int
|> optional "name" string "blah"
|> required "email" string
result : Result String User
result =
Decode.decodeString
userDecoder
"""
{"id": 123, "email": "sam@example.com" }
"""
-- Ok { id = 123, name = "blah", email = "sam@example.com" }
Because valDecoder
is given an opportunity to decode null
values before
resorting to the fallback
, you can distinguish between missing and null
values if you need to:
userDecoder2 =
Decode.succeed User
|> required "id" int
|> optional "name" (oneOf [ string, null "NULL" ]) "MISSING"
|> required "email" string
optionalAt : List String -> Json.Decode.Decoder a -> a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Decode an optional nested field.
hardcoded : a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Rather than decoding anything, use a fixed value for the next step in the
pipeline. harcoded
does not look at the JSON at all.
import Json.Decode as Decode exposing (Decoder, int, string)
import Json.Decode.Pipeline exposing (required)
type alias User =
{ id : Int
, email : String
, followers : Int
}
userDecoder : Decoder User
userDecoder =
Decode.succeed User
|> required "id" int
|> required "email" string
|> hardcoded 0
result : Result String User
result =
Decode.decodeString
userDecoder
"""
{"id": 123, "email": "sam@example.com"}
"""
-- Ok { id = 123, email = "sam@example.com", followers = 0 }
custom : Json.Decode.Decoder a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
Run the given decoder and feed its result into the pipeline at this point.
Consider this example.
import Json.Decode as Decode exposing (Decoder, at, int, string)
import Json.Decode.Pipeline exposing (custom, required)
type alias User =
{ id : Int
, name : String
, email : String
}
userDecoder : Decoder User
userDecoder =
Decode.succeed User
|> required "id" int
|> custom (at [ "profile", "name" ] string)
|> required "email" string
result : Result String User
result =
Decode.decodeString
userDecoder
"""
{
"id": 123,
"email": "sam@example.com",
"profile": {"name": "Sam"}
}
"""
-- Ok { id = 123, name = "Sam", email = "sam@example.com" }
resolve : Json.Decode.Decoder (Json.Decode.Decoder a) -> Json.Decode.Decoder a
Convert a Decoder (Result x a)
into a Decoder a
. Useful when you want
to perform some custom processing just before completing the decoding operation.
import Json.Decode as Decode exposing (Decoder, float, int, string)
import Json.Decode.Pipeline exposing (required, resolve)
type alias User =
{ id : Int
, email : String
}
userDecoder : Decoder User
userDecoder =
let
-- toDecoder gets run *after* all the
-- (|> required ...) steps are done.
toDecoder : Int -> String -> Int -> Decoder User
toDecoder id email version =
if version > 2 then
Decode.succeed (User id email)
else
fail "This JSON is from a deprecated source. Please upgrade!"
in
Decode.succeed toDecoder
|> required "id" int
|> required "email" string
|> required "version" int
-- version is part of toDecoder,
|> resolve
-- but it is not a part of User
result : Result String User
result =
Decode.decodeString
userDecoder
"""
{"id": 123, "email": "sam@example.com", "version": 1}
"""
-- Err "This JSON is from a deprecated source. Please upgrade!"