Encoding Scala None to JSON value using circe

后端 未结 2 2073
陌清茗
陌清茗 2020-12-16 17:40

Suppose I have the following case classes that need to be serialized as JSON objects using circe:

@JsonCodec
case class A(a1: String, a2: Option[String])

@J         


        
2条回答
  •  春和景丽
    2020-12-16 18:06

    The best way to do this is probably just to add a post-processing step to a semi-automatically derived encoder for B:

    import io.circe.{ Decoder, JsonObject, ObjectEncoder }
    import io.circe.generic.JsonCodec
    import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
    
    @JsonCodec
    case class A(a1: String, a2: Option[String])
    case class B(b1: Option[A], b2: Option[A], b3: Int)
    
    object B {
      implicit val decodeB: Decoder[B] = deriveDecoder[B]
      implicit val encodeB: ObjectEncoder[B] = deriveEncoder[B].mapJsonObject(
        _.filter {
          case ("b1", value) => !value.isNull
          case _ => true
        }
      )
    }
    

    And then:

    scala> import io.circe.syntax._
    import io.circe.syntax._
    
    scala> B(None, None, 1).asJson.noSpaces
    res0: String = {"b2":null,"b3":1}
    

    You can adjust the argument to the filter to remove whichever null-valued fields you want from the JSON object (here I'm just removing b1 in B).

    It's worth noting that currently you can't combine the @JsonCodec annotation and an explicitly defined instance in the companion object. This isn't an inherent limitation of the annotation—we could check the companion object for "overriding" instances during the macro expansion, but doing so would make the implementation substantially more complicated (right now it's quite simple). The workaround is pretty simple (just use deriveDecoder explicitly), but of course we'd be happy to consider an issue requesting support for mixing and matching @JsonCodec and explicit instances.

提交回复
热议问题