【问题标题】:Scala Play implicit read catch nullScala Play 隐式读取捕获 null
【发布时间】:2019-01-10 02:46:54
【问题描述】:


我正在使用外部服务,我希望收到一个包含具有三种值的字段的 json:

  • 双重
  • 该字段可能不存在

我需要将 json 反序列化为案例类,并在代码中的其他位置将其序列化为具有相同字段的 json。
我有一个隐式读写:

implicit lazy val aReads: Reads[A] = (
  "foo".readNullable[Double]
)(A.apply _)

implicit lazy aWrites: OWrites[A] = (
  "foo".write[Option[Double]]
)

和案例类:

case class A(
  foo: Option[Double]
)

正如您可以想象的那样,问题是当值不存在时我无法“捕捉”,如果使用 "foo".writeNullable[Double] 作为作家,我无法捕捉到它为空(它将始终不存在)。我该如何解决这个问题?

【问题讨论】:

  • 当字段为null 时会发生什么?你序列化什么?
  • 如果我使用写入 "foo".write[Option[Double]] 并对其进行序列化,它将是 "foo"->null,如果它不存在,它将是相同的。
  • 我想我没有遵循你的思路。是否要序列化"foo": null
  • 我想要一个等于输入的输出:如果我收到"foo": null,我想将它序列化为空。同时,如果该字段不存在,我不想在输出中包含它。我现在说清楚了吗?
  • 是的,现在我跟着 :)

标签: json scala serialization playframework


【解决方案1】:

你需要的其实是一种反映三种状态的数据类型:

  • 现在
  • 不存在

其实有一个nice encoding of this here,语义上等价于:

sealed trait Tristate[+A]
case class Present[+A](a: A) extends Tristate[A]
case object Absent extends Tristate[Nothing] // this can represent your "null" state
case object NonExisting extends Tristate[Nothing]

链接的小型库在Tristate 上有很好的组合器,例如mapflatMapfilter 等。

然后,您可以派生一个播放解码器/编码器,它将对象置于正确的状态,并进行适当的序列化。

【讨论】:

  • 非常感谢!使用相同的逻辑,使用包含在选项中的 Duostate 还不够吗?在这种情况下,特征将“捕获”存在和不存在,并且选项将处理非存在。你怎么看?
  • 是的,但它的美妙之处在于你根本不需要Option :)
  • 我刚刚完成了实现。最后,我决定简单地将三态依赖添加到我的项目中,因为其中还有解码器/编码器。
  • 好的。请注意,虽然这是一个小项目,但我不确定它是否得到维护
猜你喜欢
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多