JSON

You will be sending lots of JSON in your programs. You use the Json.Decode library to convert wild and crazy JSON into nicely structured Elm values.

The core concept for working with JSON is called a decoder. It decodes JSON values into Elm values. We will start out by looking at some very basic decoders and then look at how to put them together to handle more complex scenarios.

So that is list, but Json.Decode can handle many other data structures too. For example, dict helps you turn a JSON object into an Elm Dict and keyValuePairs helps you turn a JSON object into an Elm list of keys and values.

Decoding Objects

We decode JSON objects with the field function. It snaps together decoders just like list:

field : String -> Decoder a -> Decoder a

So when you say field "x" int you are saying (1) I want a JSON object, (2) it should have a field x, and (3) the value at x should be an integer. So using it looks like this:

Notice that the field "x" int decoder only cares about field x. The object can have other fields with other content. That is all separate. But what happens when you want to get information from many fields? Well, we just need to put together many decoders. This is possible with functions like map2:

map2 : (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value

This function takes in two different decoders. If they are both successful, it uses the given function to combine their results. So now we can put together two different decoders:

You can have optional and hardcoded fields as well. It is quite a nice library, so take a look!

Broader Context

By now you have seen a pretty big chunk of the actual Json.Decode API, so I want to give some additional context about how this fits into the broader world of Elm and web apps.

Validating Server Data

The conversion from JSON to Elm doubles as a validation phase. You are not just converting from JSON, you are also making sure that JSON conforms to a particular structure.

In fact, decoders have revealed weird data coming from NoRedInk’s backend code! If your server is producing unexpected values for JavaScript, the client just gradually crashes as you run into missing fields. In contrast, Elm recognizes JSON values with unexpected structure, so NoRedInk gives a nice explanation to the user and logs the unexpected value. This has actually led to some patches in their Ruby server!

A General Pattern

JSON decoders are an example of a more general pattern in Elm. You see it whenever you want to wrap up complicated logic into small building blocks that snap together easily. Other examples include:

Random — The Random library has the concept of a Generator. So a Generator Int creates random integers. You start with primitive building blocks that generate random Int or Bool. From there, you use functions like list and map to build up generators for fancier types.

Easing — The Easing library has the concept of an Interpolation. An Interpolation Float describes how to slide between two floating point numbers. You start with interpolations for primitives like Float or Color. The cool thing is that these interpolations compose, so you can build them up for much fancier types.

As of this writing, there is some early work on Protocol Buffers (binary data format) that uses the same pattern. In the end you get a nice composable API for converting between Elm values and binary!