This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

Json.Decode

Turn JSON values into Elm values. Definitely check out this intro to JSON decoders to get a feel for how this library works!

Primitives

type Decoder a = Decoder

A value that knows how to decode JSON values.

string : Decoder String

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 ...
bool : Decoder Bool

Decode a JSON boolean 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 ...
int : Decoder Int

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 ...
float : Decoder Float

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 ...

Data Structures

nullable : Decoder a -> Decoder (Maybe a)

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 ..
list : Decoder a -> Decoder (List a)

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]
array : Decoder a -> Decoder (Array a)

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])
dict : Decoder a -> Decoder (Dict String a)

Decode a JSON object into an Elm Dict.

decodeString (dict int) "{ \"alice\": 42, \"bob\": 99 }"
  == Dict.fromList [("alice", 42), ("bob", 99)]
keyValuePairs : Decoder a -> Decoder (List (String, a))

Decode a JSON object into an Elm List of pairs.

decodeString (keyValuePairs int) "{ \"alice\": 42, \"bob\": 99 }"
  == [("alice", 42), ("bob", 99)]

Object Primitives

field : String -> Decoder a -> Decoder a

Decode a JSON object, requiring a particular field.

decodeString (field "x" int) "{ \"x\": 3 }"            == Ok 3
decodeString (field "x" int) "{ \"x\": 3, \"y\": 4 }"  == Ok 3
decodeString (field "x" int) "{ \"x\": true }"         == Err ...
decodeString (field "x" int) "{ \"y\": 4 }"            == Err ...

decodeString (field "name" string) "{ \"name\": \"tom\" }" == Ok "tom"

The object can have other fields. Lots of them! The only thing this decoder cares about is if x is present and that the value there is an Int.

Check out map2 to see how to decode multiple fields!

at : List String -> Decoder a -> Decoder a

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 "42

This is really just a shorthand for saying things like:

field "person" (field "name" string) == at ["person","name"] string
index : Int -> Decoder a -> Decoder a

Decode 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 ...

Inconsistent Structure

maybe : Decoder a -> Decoder (Maybe a)

Helpful for dealing with optional fields. Here are a few slightly different examples:

json = """{ "name": "tom", "age": 42 }"""

decodeString (maybe (field "age"    int  )) json == Ok (Just 42)
decodeString (maybe (field "name"   int  )) json == Ok Nothing
decodeString (maybe (field "height" float)) json == Ok Nothing

decodeString (field "age"    (maybe int  )) json == Ok (Just 42)
decodeString (field "name"   (maybe int  )) json == Ok Nothing
decodeString (field "height" (maybe float)) 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.

oneOf : List (Decoder a) -> Decoder a

Try a bunch of different decoders. 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.

import String

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.

Run Decoders

decodeString : Decoder a -> String -> Result String a

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 ...
decodeValue : Decoder a -> Value -> Result String a

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.

type alias Value = JsEncode.Value

A JSON value.

Mapping

Note: If you run out of map functions, take a look at elm-decode-pipeline which makes it easier to handle large objects, but produces lower quality type errors.

map : (a -> value) -> Decoder a -> Decoder value

Transform a decoder. Maybe you just want to know the length of a string:

import String

stringLength : Decoder Int
stringLength =
  map String.length string

It is often helpful to use map with oneOf, like when defining nullable:

nullable : Decoder a -> Decoder (Maybe a)
nullable decoder =
  oneOf
    [ null Nothing
    , map Just decoder
    ]
map2 : (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value

Try two decoders and then combine the result. We can use this to decode objects with many fields:

type alias Point = { x : Float, y : Float }

point : Decoder 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.

map3 : (a -> b -> c -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder value

Try three decoders and then combine the result. We can use this to decode objects with many fields:

type alias Person = { name : String, age : Int, height : Float }

person : Decoder Person
person =
  map3 Person
    (at ["name"] string)
    (at ["info","age"] int)
    (at ["info","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!

map4 : (a -> b -> c -> d -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder value
map5 : (a -> b -> c -> d -> e -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder value
map6 : (a -> b -> c -> d -> e -> f -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder value
map7 : (a -> b -> c -> d -> e -> f -> g -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder g -> Decoder value
map8 : (a -> b -> c -> d -> e -> f -> g -> h -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder g -> Decoder h -> Decoder value

Fancy Decoding

lazy : (() -> Decoder a) -> Decoder a

Sometimes you have JSON with recursive structure, like nested comments. You can use lazy to make sure your decoder unrolls lazily.

type alias Comment =
  { message : String
  , responses : Responses
  }

type Responses = Responses (List Comment)

comment : Decoder Comment
comment =
  map2 Comment
    (field "message" string)
    (field "responses" (map Responses (list (lazy (\_ -> comment)))))

If we had said list comment instead, we would start expanding the value infinitely. What is a comment? It is a decoder for objects where the responses field contains comments. What is a comment though? Etc.

By using list (lazy (\_ -> comment)) we make sure the decoder only expands to be as deep as the JSON we are given. You can read more about recursive data structures here.

value : Decoder Value

Do not do anything with a JSON value, just bring it into Elm as a Value. This can be useful if you have particularly crazy data that you would like to deal with later. Or if you are going to send it out a port and do not care about its structure.

null : a -> Decoder a

Decode a null value into some Elm value.

decodeString (null False) "null" == Ok False
decodeString (null 42) "null"    == Ok 42
decodeString (null 42) "42"      == Err ..
decodeString (null 42) "false"   == Err ..

So if you ever see a null, this will return whatever value you specified.

succeed : a -> Decoder a

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.

fail : String -> Decoder a

Ignore the JSON and make the decoder 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.

andThen : (a -> Decoder b) -> Decoder a -> Decoder b

Create decoders that depend on previous results. If you are creating versioned data, you might do something like this:

info : Decoder Info
info =
  field "version" int
    |> andThen infoHelp

infoHelp : Int -> Decoder Info
infoHelp version =
  case version of
    4 ->
      infoDecoder4

    3 ->
      infoDecoder3

    _ ->
      fail <|
        "Trying to decode info, but version "
        ++ toString version ++ " is not supported."

-- infoDecoder4 : Decoder Info
-- infoDecoder3 : Decoder Info
module Json.Decode exposing
  ( Decoder, string, bool, int, float
  , nullable, list, array, dict, keyValuePairs
  , field, at, index
  , maybe, oneOf
  , decodeString, decodeValue, Value
  , map, map2, map3, map4, map5, map6, map7, map8
  , lazy, value, null, succeed, fail, andThen
  )

{-| Turn JSON values into Elm values. Definitely check out this [intro to
JSON decoders][guide] to get a feel for how this library works!

[guide]: https://guide.elm-lang.org/interop/json.html

# Primitives
@docs Decoder, string, bool, int, float

# Data Structures
@docs nullable, list, array, dict, keyValuePairs

# Object Primitives
@docs field, at, index

# Inconsistent Structure
@docs maybe, oneOf

# Run Decoders
@docs decodeString, decodeValue, Value

# Mapping

**Note:** If you run out of map functions, take a look at [elm-decode-pipeline][pipe]
which makes it easier to handle large objects, but produces lower quality type
errors.

[pipe]: http://package.elm-lang.org/packages/NoRedInk/elm-decode-pipeline/latest

@docs map, map2, map3, map4, map5, map6, map7, map8

# Fancy Decoding
@docs lazy, value, null, succeed, fail, andThen
-}


import Array exposing (Array)
import Dict exposing (Dict)
import Json.Encode as JsEncode
import List
import Maybe exposing (Maybe(..))
import Result exposing (Result(..))
import Native.Json



-- PRIMITIVES


{-| A value that knows how to decode JSON values.
-}
type Decoder a = Decoder


{-| 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 ...
-}
string : Decoder String
string =
  Native.Json.decodePrimitive "string"


{-| Decode a JSON boolean 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 ...
-}
bool : Decoder Bool
bool =
  Native.Json.decodePrimitive "bool"


{-| 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 ...
-}
int : Decoder Int
int =
  Native.Json.decodePrimitive "int"


{-| 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 ...
-}
float : Decoder Float
float =
  Native.Json.decodePrimitive "float"



-- DATA STRUCTURES


{-| 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 ..
-}
nullable : Decoder a -> Decoder (Maybe a)
nullable decoder =
  oneOf
    [ null Nothing
    , map Just decoder
    ]


{-| 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]
-}
list : Decoder a -> Decoder (List a)
list decoder =
  Native.Json.decodeContainer "list" decoder


{-| 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])
-}
array : Decoder a -> Decoder (Array a)
array decoder =
  Native.Json.decodeContainer "array" decoder


{-| Decode a JSON object into an Elm `Dict`.

    decodeString (dict int) "{ \"alice\": 42, \"bob\": 99 }"
      == Dict.fromList [("alice", 42), ("bob", 99)]
-}
dict : Decoder a -> Decoder (Dict String a)
dict decoder =
  map Dict.fromList (keyValuePairs decoder)


{-| Decode a JSON object into an Elm `List` of pairs.

    decodeString (keyValuePairs int) "{ \"alice\": 42, \"bob\": 99 }"
      == [("alice", 42), ("bob", 99)]
-}
keyValuePairs : Decoder a -> Decoder (List (String, a))
keyValuePairs =
  Native.Json.decodeKeyValuePairs



-- OBJECT PRIMITIVES


{-| Decode a JSON object, requiring a particular field.

    decodeString (field "x" int) "{ \"x\": 3 }"            == Ok 3
    decodeString (field "x" int) "{ \"x\": 3, \"y\": 4 }"  == Ok 3
    decodeString (field "x" int) "{ \"x\": true }"         == Err ...
    decodeString (field "x" int) "{ \"y\": 4 }"            == Err ...

    decodeString (field "name" string) "{ \"name\": \"tom\" }" == Ok "tom"

The object *can* have other fields. Lots of them! The only thing this decoder
cares about is if `x` is present and that the value there is an `Int`.

Check out [`map2`](#map2) to see how to decode multiple fields!
-}
field : String -> Decoder a -> Decoder a
field =
    Native.Json.decodeField


{-| 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 "42

This is really just a shorthand for saying things like:

    field "person" (field "name" string) == at ["person","name"] string
-}
at : List String -> Decoder a -> Decoder a
at fields decoder =
    List.foldr field decoder fields


{-| Decode 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 ...
-}
index : Int -> Decoder a -> Decoder a
index =
    Native.Json.decodeIndex



-- WEIRD STRUCTURE


{-| Helpful for dealing with optional fields. Here are a few slightly different
examples:

    json = """{ "name": "tom", "age": 42 }"""

    decodeString (maybe (field "age"    int  )) json == Ok (Just 42)
    decodeString (maybe (field "name"   int  )) json == Ok Nothing
    decodeString (maybe (field "height" float)) json == Ok Nothing

    decodeString (field "age"    (maybe int  )) json == Ok (Just 42)
    decodeString (field "name"   (maybe int  )) json == Ok Nothing
    decodeString (field "height" (maybe float)) 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`.
-}
maybe : Decoder a -> Decoder (Maybe a)
maybe decoder =
  Native.Json.decodeContainer "maybe" decoder


{-| Try a bunch of different decoders. 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`.

    import String

    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.
-}
oneOf : List (Decoder a) -> Decoder a
oneOf =
    Native.Json.oneOf



-- MAPPING


{-| Transform a decoder. Maybe you just want to know the length of a string:

    import String

    stringLength : Decoder Int
    stringLength =
      map String.length string

It is often helpful to use `map` with `oneOf`, like when defining `nullable`:

    nullable : Decoder a -> Decoder (Maybe a)
    nullable decoder =
      oneOf
        [ null Nothing
        , map Just decoder
        ]
-}
map : (a -> value) -> Decoder a -> Decoder value
map =
    Native.Json.map1


{-| Try two decoders and then combine the result. We can use this to decode
objects with many fields:

    type alias Point = { x : Float, y : Float }

    point : Decoder 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.
-}
map2 : (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value
map2 =
    Native.Json.map2


{-| Try three decoders and then combine the result. We can use this to decode
objects with many fields:

    type alias Person = { name : String, age : Int, height : Float }

    person : Decoder Person
    person =
      map3 Person
        (at ["name"] string)
        (at ["info","age"] int)
        (at ["info","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!
-}
map3 : (a -> b -> c -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder value
map3 =
    Native.Json.map3


{-|-}
map4 : (a -> b -> c -> d -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder value
map4 =
    Native.Json.map4


{-|-}
map5 : (a -> b -> c -> d -> e -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder value
map5 =
    Native.Json.map5


{-|-}
map6 : (a -> b -> c -> d -> e -> f -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder value
map6 =
    Native.Json.map6


{-|-}
map7 : (a -> b -> c -> d -> e -> f -> g -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder g -> Decoder value
map7 =
    Native.Json.map7


{-|-}
map8 : (a -> b -> c -> d -> e -> f -> g -> h -> value) -> Decoder a -> Decoder b -> Decoder c -> Decoder d -> Decoder e -> Decoder f -> Decoder g -> Decoder h -> Decoder value
map8 =
    Native.Json.map8



-- RUN DECODERS


{-| 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 ...
-}
decodeString : Decoder a -> String -> Result String a
decodeString =
  Native.Json.runOnString


{-| 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.
-}
decodeValue : Decoder a -> Value -> Result String a
decodeValue =
  Native.Json.run


{-| A JSON value.
-}
type alias Value = JsEncode.Value



-- FANCY PRIMITIVES


{-| 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`.
-}
succeed : a -> Decoder a
succeed =
  Native.Json.succeed


{-| Ignore the JSON and make the decoder 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`](#andThen) docs for an example.
-}
fail : String -> Decoder a
fail =
  Native.Json.fail


{-| Create decoders that depend on previous results. If you are creating
versioned data, you might do something like this:

    info : Decoder Info
    info =
      field "version" int
        |> andThen infoHelp

    infoHelp : Int -> Decoder Info
    infoHelp version =
      case version of
        4 ->
          infoDecoder4

        3 ->
          infoDecoder3

        _ ->
          fail <|
            "Trying to decode info, but version "
            ++ toString version ++ " is not supported."

    -- infoDecoder4 : Decoder Info
    -- infoDecoder3 : Decoder Info
-}
andThen : (a -> Decoder b) -> Decoder a -> Decoder b
andThen =
  Native.Json.andThen


{-| Sometimes you have JSON with recursive structure, like nested comments.
You can use `lazy` to make sure your decoder unrolls lazily.

    type alias Comment =
      { message : String
      , responses : Responses
      }

    type Responses = Responses (List Comment)

    comment : Decoder Comment
    comment =
      map2 Comment
        (field "message" string)
        (field "responses" (map Responses (list (lazy (\_ -> comment)))))

If we had said `list comment` instead, we would start expanding the value
infinitely. What is a `comment`? It is a decoder for objects where the
`responses` field contains comments. What is a `comment` though? Etc.

By using `list (lazy (\_ -> comment))` we make sure the decoder only expands
to be as deep as the JSON we are given. You can read more about recursive data
structures [here][].

[here]: https://github.com/elm-lang/elm-compiler/blob/master/hints/recursive-alias.md
-}
lazy : (() -> Decoder a) -> Decoder a
lazy thunk =
  andThen thunk (succeed ())


{-| Do not do anything with a JSON value, just bring it into Elm as a `Value`.
This can be useful if you have particularly crazy data that you would like to
deal with later. Or if you are going to send it out a port and do not care
about its structure.
-}
value : Decoder Value
value =
  Native.Json.decodePrimitive "value"


{-| Decode a `null` value into some Elm value.

    decodeString (null False) "null" == Ok False
    decodeString (null 42) "null"    == Ok 42
    decodeString (null 42) "42"      == Err ..
    decodeString (null 42) "false"   == Err ..

So if you ever see a `null`, this will return whatever value you specified.
-}
null : a -> Decoder a
null =
  Native.Json.decodeNull