November 17, 2025

Working With JSON Decoders

In this tutorial, you will learn about JSON encoders and decoders. We would start with JSON Decoders.

We would cover the following:

  1. Understanding JSON Decoders
  2. Building Decoders
  3. Combining Decoders
  4. Nesting Decoders

 

1. JSON Decoders

First we need to understand what JSON decoding means. If we have some JSON structure, for example:

{
    "firstname" : "Kindson",
    "lastname" : "Munonye",
    "age" : 40
}

 

For this structure to be useful in an Elm code, we need to extract the values from this JSON object. Why? Since Elm is a pure functional language, we cannot just pass in a raw JSON structure as it may lead to undesirable side effect. So we need not process the JSON structure and extract the values into Elm data types.

For the example above, we would need two decoders:

  • Decoder String – to extract the String values
  • Decoder Int – to extract the Int values

These two decoders are given in the next section.

 

2. Building Decoders

So how do we build these decoders?

Elm provides little decoders for decoding different data types. These decoders are available in the Json.Decode module.  To use this module you need to install the elm/json library using elm install.

firstnameDecoder : Decoder String
firstnameDecoder =
    field "firstname" string

lastnameDecoder : Decoder String
lastnameDecoder =
    field "lastname" string
   
ageDecoder : Decoder Int
ageDecoder  =
    field "age" int

 

So you can see that we can build decoders for various data types. What if we have a custom data type? Let’s see that in the next section.

 

3. Combining Decoders

Assuming we have a custom type Student that has two fields as shown below:

type alias Student =
    { name: String
    , age : Int
    }

 

We would like build a decoder that takes a json string  and returns a Student object. To this we need to combine two decoders using the map2 function. This function person object, and the two fields to be decoded. The resulting combined decoder is given below:

studentDecoder : Decoder Student
studentDecoder =
    map2 Student
    (Decode.field "name" string)
    (Decode.field "age" int)

 

So if we use the studentDecoder on

{ "name": "Kindson", "age": 40 }

We would have a Student object

 

4. Nesting Decoder

Sometimes, we may have JSON objects that have nested objects.  In this case, we need to think about decoders for both the parent structure and the nested structure. For example, the json below is structure with a nested object.

{
  "subject": "Literature in English",
  "department": "Language Studies",
  "student":
  {
    "name": "Kindson Munonye",
    "age": 40,
    "location": "Budapest"
  },
  "year": 54
}

 

This structure represents an exam that a student enrols in. The equivalent Elm object is the record below:

type alias Exam =
    { subject: String
    , department: String
    , student: Student
    , year: Int
    }

 

The encoder for this would then use the studentEncoder we built earlier on like this:

examDecoder =
    map4 Exam
    (Decode.field "subject" string)
    (Decode.field "department" string)
    (Decode.field "student" studentDecoder)
    (Decode.field "age" int)

Leave a Reply