使用circe将Scala None编码为JSON值 [英] Encoding Scala None to JSON value using circe

查看:150
本文介绍了使用circe将Scala None编码为JSON值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下案例类需要使用circe序列化为JSON对象:

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])

@JsonCodec
case class B(b1: Option[A], b2: Option[A], b3: Int)

现在我需要将val b = B(None, Some(A("a", Some("aa")), 5)编码为JSON,但我希望能够控制是否将其输出为

Now I need to encode val b = B(None, Some(A("a", Some("aa")), 5) as JSON but I want to be able to control whether it is output as

{
  "b1": null,
  "b2": {
          "a1": "a",
          "a2": "aa"
        },
  "b3": 5
}

{
  "b2": {
          "a1": "a",
          "a2": "aa"
        },
  "b3": 5
}

使用Printer另请参阅此问题).但是,如何才能在每个字段的基础上控制此设置?

Using Printer's dropNullKeys config, e.g. b.asJson.noSpaces.copy(dropNullKeys = true) would result in omitting Nones from output whereas setting it to false would encode Nones as null (see also this question). But how can one control this setting on a per field basis?

推荐答案

做到这一点的最佳方法可能只是为半自动派生的B编码器添加一个后处理步骤:

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
    }
  )
}

然后:

scala> import io.circe.syntax._
import io.circe.syntax._

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

您可以将过滤器的参数调整为从JSON对象中删除所需的任何空值字段(这里我只是在B中删除b1).

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).

值得注意的是,当前您无法将@JsonCodec批注和伴随对象中的显式定义的实例结合在一起.这不是注解的固有限制-我们可以在宏扩展过程中检查伴随对象的覆盖"实例,但是这样做会使实现变得更加复杂(现在非常简单).解决方法非常简单(只需显式使用deriveDecoder),但是当然我们很乐意考虑一个问题,要求支持混合和匹配@JsonCodec和显式实例.

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.

这篇关于使用circe将Scala None编码为JSON值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆