I’ve always found JSON encoders to be easier to understand than decoders. Encoders are just functions that take some Elm data type as input and return a Json.Encode.Value. Then you can give that Value to Json.Encode.encode to turn it into a JSON string.
But what are decoders? They have the type Decoder a, but what is that really?
To learn more thoroughly how decoders work, I implemented elm/json in Elm. Here’s the result:
The key insight I gained is: Decoders are just functions in disguise. They are functions that take a raw JSON value as input, and return a Result.
You can think of a decoder like this:
type Decoder a = Json.Decode.Value -> Result Json.Decode.Error a
Except that you can’t call those functions manually. Only Json.Decode.decodeString and Json.Decode.decodeValue can. Once I understood this, decoders didn’t feel so magical anymore.
A couple of other little things I learned:
-
Json.Decode.ValueandJson.Encode.Valueare actually the same type. It’s defined inJson.EncodeandJson.Decodeexposes an alias. -
Json.Decode.oneOf []always fails. Not because the JSON input is invalid, but because of the empty list of decoders. -
Json.Decode.indexchecks for too large index but not too small (issue). - Recursive fuzzing with elm-test.

