October 3, 2025

Scala – Building Json Decoders With Circe

In the previous two tutorials, we covers how to build Json encoders in Scala using Circe. You can review them here:

In this tutorial, we would cover how to build Json Decoders in Scala using Circe. So let’s get started

  1. Create Some Author and Article Json Objects
  2. Building Decoders Using ProductN
  3. Using our Decoder to Decode
  4. Using DecodeAccumulating Function
  5. Using For Comprehension

 

1. Create some Author and Article Json

Remember that a decoder is used to decode some Json value into a type. Now let’s create some Json values that we would be using to test the decode we’ll build.

// Create two Author Json Objects, one valid and on inValid
val validAuthor = Json.obj(
    "name" -> "Kindson".asJson
)
val invalidAuthor = Json.obj(
    "name" -> 45.asJson
)

 

Then we also create two more Json objects for article

// Create two Article objects
val validArticle: Json = Json.obj(
    "id" ->  "5cc24c45-e692-45d5-8092-64c73d886abd".asJson,
    "title" -> "Candle in the wind".asJson,
    "content" -> "..".asJson,
    "author" -> Json.obj(
        "name" -> "John Munonye".asJson
    )
)

val inValidArticle: Json = Json.obj(
    "id" ->  "5cc24c45-e692-45d5-8092-64c73d886abd".asJson,
    "content" ->998.asJson,
    "author" -> Json.obj(
        "name" -> "John Munonye".asJson
    )
)

 

2. Building Decoders Using forProductN

The easiest way to define a decoder is the use the forProductN method of the decoder where N is the number of fields in the case class. This method take the two parameter lists as specified. The second parameter list expects a function that can build the Author instance out of the two arguments provided. This is the Apply method. The complete decoder is given below:

// Build an author decoder using the forProductN method of the Docoder
implicit val authorDecoder = Decoder.forProduct2("name", "bio")(Author.apply)

 

Decoders built in this way using the forProductN is known as applicative-based decoders and it gives us the ability to accumulate errors. However, this limits our ability to model complex logic

 

3. Using Our Decoder to Decode

Given our decoder, we can convert our validAuthor into an instance of Author using one of two ways:

Method 1 – using hcursor

// Perform decoding using the hcursor method
authorDecoder(validAuthor.hcursor)

 

Method 2 – using as() method

// Perform decoding by calling the .as() method on the Json Object
validAuthor.as[Author]

This gives use a Decode Result which could either be a decode failure on the Left, or a valid author instance on the Right

 

4. Using Decode Accumulating Method

The decodeAccumulating method can be used as well to perform decoding. The benefit of the decodeAccumulating method is that it can give a list of decoding failures indicates all the problems with the Json object.

// Using the DecodeAccumulating method to perform decoding. This approach helps us accumulate errors
authorDecoder.decodeAccumulating(invalidAuthor.hcursor)

 

5. Decoder for Article Using for() Comprehension

We would create a function and in the body of that function, we would decode every field one by one and in the final yield we build an instance of Article.

// Build an article decoder using the for comprehension
implicit val articleDecoder: Decoder[Article] = json =>
    for {
        id <- json.get[UUID]("id")
        title <- json.get[String]("title")
        content <- json.get[String]("content")
        author <- json.get[Author]("author")
    } yield Article(id, title, content, author)

Note that the direction of the arrows indicate that decoded field are assigned to variables. In the yield, we then build an Article instance using these variables that we obtained from decoding. This is called monadic decoders and it gives us the ability to model complex logic  but we’ll not have error accumulation.

In the same way we can decode the Article Json object using this new decoder. We can use either hcursor or as() method as earlier explained.

 

Exercise

Create a couple of invalid Json Articles and try to decode them

Leave a Reply