Using Elm’s Json.Decode for Safe API Responses
Elm’s Json.Decode turns JSON into Elm values safely, returning Ok on success or a descriptive Err on failure—no runtime exceptions.
12 Feb 2026, 23:27 UTC

Useful answer
Elm’s Json.Decode module lets you turn incoming JSON into Elm values without ever throwing a runtime exception. A successful decode guarantees the data matches the shape you declared; a failure returns a descriptive Err value that you can handle like any other result.
Worked example
Suppose you receive a JSON object representing a user:
{
"name": "Ada Lovelace",
"age": 36,
"email": "ada@example.com"
}
First define an Elm type alias and a decoder that maps the three fields:
module User exposing (User, userDecoder)
import Json.Decode exposing (Decoder, map3, string, int, field)
type alias User =
{ name : String
, age : Int
, email : String
}
userDecoder : Decoder User
userDecoder =
map3 User
(field "name" string)
(field "age" int)
(field "email" string)
To decode a JSON string, call Json.Decode.decodeString:
import Json.Decode exposing (decodeString)
decodeUser : String -> Result String User
decodeUser json =
decodeString userDecoder json
When the JSON matches the schema, decodeUser returns Ok user. If the JSON is malformed or missing a field, it returns Err with a message such as "Field 'age' not found".
Limits and common mistakes
Limits
- Decoders are pure functions; they cannot perform side effects such as logging or making additional requests.
- Deeply nested structures may require many combinators, which can become verbose.
- Decoding very large payloads can be slower than a hand‑written parser in another language, though for typical API responses the difference is negligible.
Common mistakes
- Forgetting to handle optional fields with
Json.Decode.maybe, causing the decoder to fail when the field is absent. - Using
Json.Decode.oneOfwithout ordering specificity, which can lead to ambiguous matches and unexpected successes. - Assuming a decoder will succeed for malformed JSON when the schema diverges; the decoder will return
Err, but ignoring that result hides the problem. - Using
Json.Decode.succeedto bypass validation; this can conceal mismatches and introduce logical bugs.
How to verify
- Create a new Elm project:
elm init(run in a terminal with write permissions to the directory). - Install the JSON package:
elm install elm/json. - Save the example code above in
src/User.elmand a minimalMain.elmthat callsdecodeUserwith a test JSON string. - Compile to JavaScript:
elm make src/Main.elm --output=main.js. - Open the generated
main.jsin a browser console or run it with Node; observe that valid JSON yieldsOk { name = "Ada Lovelace", age = 36, email = "ada@example.com" }and invalid JSON yields anErrwith a descriptive message. - To confirm error handling, remove the "age" field from the JSON string and re‑run; the result should be
Err "Field 'age' not found".
These steps let you see that the decoder enforces the schema and that failures are explicit values you can handle.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.