Build GraphQL with decoders for turning JSON values into Elm values.
Decode a JSON string into an Elm String.
decodeString string "true" == Err ...
decodeString string "42" == Err ...
decodeString string "3.14" == Err ...
decodeString string "\"hello\"" == Ok "hello"
decodeString string "{ \"hello\": 42 }" == Err ...Decode a JSON string into an Elm Bool.
decodeString bool "true" == Ok True
decodeString bool "42" == Err ...
decodeString bool "3.14" == Err ...
decodeString bool "\"hello\"" == Err ...
decodeString bool "{ \"hello\": 42 }" == Err ...Decode a JSON number into an Elm Int.
decodeString int "true" == Err ...
decodeString int "42" == Ok 42
decodeString int "3.14" == Err ...
decodeString int "\"hello\"" == Err ...
decodeString int "{ \"hello\": 42 }" == Err ...Decode a JSON number into an Elm Float.
decodeString float "true" == Err ..
decodeString float "42" == Ok 42
decodeString float "3.14" == Ok 3.14
decodeString float "\"hello\"" == Err ...
decodeString float "{ \"hello\": 42 }" == Err ...Decode a nullable JSON value into an Elm value.
decodeString (nullable int) "13" == Ok (Just 13)
decodeString (nullable int) "42" == Ok (Just 42)
decodeString (nullable int) "null" == Ok Nothing
decodeString (nullable int) "true" == Err ...Decode a JSON array into an Elm List.
decodeString (list int) "[1,2,3]" == Ok [ 1, 2, 3 ]
decodeString (list bool) "[true,false]" == Ok [ True, False ]Decode a JSON array into an Elm Array.
decodeString (array int) "[1,2,3]" == Ok (Array.fromList [ 1, 2, 3 ])
decodeString (array bool) "[true,false]" == Ok (Array.fromList [ True, False ])Decode a nested JSON object, requiring certain fields.
json = """{ "person": { "name": "tom", "age": 42 } }"""
decodeString (at ["person", "name"] string) json == Ok "tom"
decodeString (at ["person", "age" ] int ) json == Ok "42This is really just a shorthand for saying things like:
field "person" [] (field "name" [] string) == at [ "person", "name" ] stringDecode a JSON array, requiring a particular index.
json = """[ "alice", "bob", "chuck" ]"""
decodeString (index 0 string) json == Ok "alice"
decodeString (index 1 string) json == Ok "bob"
decodeString (index 2 string) json == Ok "chuck"
decodeString (index 3 string) json == Err ...Helpful for dealing with optional fields. Here are a few slightly different examples:
json = """{ "name": "tom", "age": 42 }"""
decodeString (field "age" [] (maybe int)) json == Ok (Just 42)
decodeString (field "name" [] (maybe int)) json == Ok Nothing
decodeString (field "height" [] (maybe int)) json == Err ...Notice the last example!
It is saying we must have a field named height and the content may be a float.
There is no height field, so the decoder fails.
Point is, maybe will make exactly what it contains conditional.
For optional fields, this means you probably want it outside a use of field or at.
Try a bunch of different selectors. This can be useful if the JSON may come
in a couple different formats. For example, say you want to read an array of
numbers, but some of them are null.
badInt : Decoder Int
badInt =
oneOf [ int, null 0 ]
-- decodeString (list badInt) "[1,2,null,4]" == Ok [1,2,0,4]Why would someone generate JSON like this? Questions like this are not good
for your health. The point is that you can use oneOf to handle situations
like this!
You could also use oneOf to help version your data. Try the latest format,
then a few older ones that you still support. You could use andThen to be
even more particular if you wanted.
Transform a selector. Maybe you just want to know the length of a string:
stringLength : Selector Int
stringLength =
map String.length stringIt is often helpful to use map with oneOf, like when defining nullable:
nullable : Selector a -> Selector (Maybe a)
nullable selector =
oneOf
[ null Nothing
, map Just selector
]Try two selectors and then combine the result We can use this to select objects with many fields:
type alias Point =
{ x : Float, y : Float }
point : Selector Point
point =
map2 Point
(field "x" [] float)
(field "y" [] float)
-- decodeString point """{ "x": 3, "y": 4 }""" == Ok { x = 3, y = 4 }It tries each individual decoder and puts the result together with the Point
constructor.
Try three selectors and then combine the result. We can use this to select objects with many fields:
type alias Person =
{ name : String, age : Int, height : Float }
person : Selector Person
person =
succeed Person
|> select "name" [] string
|> select age" [] int
|> select "height" [] float
-- json = """{ "name": "tom", "info": { "age": 42, "height": 1.8 } }"""
-- decodeString person json == Ok { name = "tom", age = 42, height = 1.8 }Like map2 it tries each decoder in order and then give the results to the
Person constructor. That can be any function though!
A JSON value.
Parse the given string into a JSON value and then run the Decoder on it. This will fail if the string is not well-formed JSON or if the Decoder fails for some reason.
decodeString int "4" == Ok 4
decodeString int "1 + 2" == Err ...Run a Decoder on some JSON Value. You can send these JSON values through ports, so that is probably the main time you would use this function.
A structured error describing exactly how the selector failed. You can use this to create more elaborate visualizations of a selector problem. For example, you could show the entire JSON object and show the part causing the failure in red.
Convert a decoding error into a String that is nice for debugging. It produces multiple lines of output, so you may want to peek at it with something like this:
import Html
import Json.Decode as Decode
errorToHtml : Decode.Error -> Html.Html msg
errorToHtml error =
Html.pre [] [ Html.text (Decode.errorToString error) ]Note: It would be cool to do nicer coloring and fancier HTML, but we
cannot have any HTML dependencies in elm/core. It is totally possible
to crawl the Error structure and create this separately though!
Create a selector that depend on previous results. Doesn't create depended Selector.
Ignore the JSON and produce a certain Elm value.
decodeString (succeed 42) "true" == Ok 42
decodeString (succeed 42) "[1,2,3]" == Ok 42
decodeString (succeed 42) "hello" == Err ... -- this is not a valid JSON string
This is handy when used with `oneOf` or `andThen`.Ignore the JSON and make the selector fail. This is handy when used with
oneOf or andThen where you want to give a custom error message in some
case.
See the andThen docs for an example.
A value that knows how to select (receive and decode) a GraphQL values.