How to define a flexible String decoder with ZIO JSON

January 20, 2023

I am using ZIO JSON to decode responses from a Web service and I’ve faced an issue : some objects have fields that can sometimes be strings and sometime be integers.

This can be solved with decoders orElse method like this :

case class SoftwareVersion(
                            name: String,
                            // ...

case class SoftwareVersionWithIntName(
                            name: Int,
                            // ...

object Decoders{
  implicit val softwareVersionDecoder = DeriveJsonDecoder.gen[SoftwareVersion].orElse(
    DeriveJsonDecoder.gen[SoftwareVersionWithIntName].map(decoded =>

It is working but if there is a lot of changing fields, it may lead to a lot of cases to manage.

To make it work at any level with the minimum amount of code, you can hack the String decoder itself :

implicit val flexStringDecoder = JsonDecoder[String].orElse(
  JsonDecoder[Int].map(decoded => decoded.toString)

Use it with caution!

The same trick should also work with Circe.

comments powered by Disqus