Skip to content

Add this helpful example for using Unions. #1319

@pwharned

Description

@pwharned

For some reason, jsoniter was not respecting an Either definition I made and failed with a deserialization error.

I was able to get this Union deserializer to work and thought you might add it to your documentation for the benefit of other users.

Heres an example if you need to use a Union type:

case class AddressRegion(
                          abbreviatedName: Option[String],
                          administrativeDivisionCode: Option[String],
                          isoSubDivisionCode: Option[String],
                          isoSubDivisionName: Option[String],
                          name: Option[String]
                        )
object DataBlocks {

  given addressRegionObjectCodec: JsonValueCodec[AddressRegion] = JsonCodecMaker.make
  given stringCodec: JsonValueCodec[String] = JsonCodecMaker.make
  given unionCodec: JsonValueCodec[String | AddressRegion] = new JsonValueCodec[String | AddressRegion] {
    def decode(in: JsonReader): String | AddressRegion = {
      // Peek at the next token to determine if it's an object or a string.
      in.nextToken() match {
        case '{' =>
          // If it's an object, try to decode it as AddressRegion
          in.rollbackToken() // Rollback the token so the AddressRegion decoder can read it
          addressRegionObjectCodec.decodeValue(in, null)
        case '"' =>
          // If it's a string, decode it as String
          in.rollbackToken() // Rollback the token so the String decoder can read it
          stringCodec.decodeValue(in, null)

        case other =>
          // For any other token, it's an unexpected type
          throw new RuntimeException(s"Expected JSON object or string, but got token: ${other.toChar}")
      }
    }
    // --- encode method ---
    def encode(x: String | AddressRegion, out: JsonWriter): Unit = {
      x match {
        case s: String => stringCodec .encodeValue(s, out)
        case ar: AddressRegion => addressRegionObjectCodec .encodeValue(ar, out)
      }
    }


    override def decodeValue(in: JsonReader, default: String | AddressRegion): String | AddressRegion = {

      decode(in)
    }

    override def encodeValue(x: String | AddressRegion, out: JsonWriter): Unit = {
      x match {
        case s: String => stringCodec .encodeValue(s, out)
        case ar: AddressRegion => addressRegionObjectCodec .encodeValue(ar, out)
      }
    }

    override def nullValue: String | AddressRegion = null
  }
  given dataBlocksCodec: JsonValueCodec[DataBlocks] = JsonCodecMaker.make
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions