使用 Play-JSON 库解析对象序列

Posted

技术标签:

【中文标题】使用 Play-JSON 库解析对象序列【英文标题】:Parsing an object-sequence with Play-JSON library 【发布时间】:2017-07-21 14:27:50 【问题描述】:

作为免责声明:我对 Scala 和一般的函数式编程非常陌生。

我有以下课程:

case class A(
  field1: String,
  field2: DateTime
)

case class B(
  listOfStuff: Seq[A]
)

object A
  def create(field1: String, field2: DateTime): A = A(field1, field2)


object B
  def create(listOfStuff: Seq[A]): B = B(listOfStuff)

(存在create() 函数是因为我在使用apply() 时有时会在我的代码中遇到问题。让我们忽略这一点,我怀疑它是否相关。)

我以 JSON 格式获取这些对象,并尝试使用 Play-JSON 库解析它们。一个重要方面是 JSON 文本中可能缺少列表 (Seq),它是一个可选字段。

考虑到这一点,这就是我写那一行的方式:

private implicit val messageReader = (
    //...
    (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq()))
    //...
)(B.create _)

编译时出现如下错误:

错误:(!line!, !column!) 找不到类型 Seq[A] 的 Json 反序列化器。 尝试为此类型实现隐式读取或格式化。

根据我在this question 中看到的内容,显然您需要为每种类型的Reads[T] 提供一个implicit 实例T,这不是语言的一部分(或类似的东西,我是否提到过我'我是新手?)

所以我还在同一范围内添加了辅助Reads[T],我的代码现在看起来像这样:

private implicit val messageReader = (
    (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq()))
)(B.create _)

private implicit val anotherReader = (
    (__ \ "field1").read[String] and
    (__ \ "field2").read[String].map(org.joda.time.DateTime.parse)
)(A.create _)

但是我仍然在同一行上遇到同样的错误。

我觉得这里有一些非常简单和明显的问题,但我无法弄清楚它是什么。

我该如何解决这个问题?

【问题讨论】:

为了能够使用Seq[T] 的解析器,T 的解析器必须可用 @cchantep 这就是我添加private implicit val anotherReader 的原因。还是不行。 它必须在 before 之前可用(而不是作为后来的 val) @cchantep 你的建议奏效了。我只是颠倒了他们的顺序,一切都很好。将其发布为答案,我会接受它;)。 【参考方案1】:

如果B.create 接受单个参数,那么它的读取可能如下所示:

private implicit val messageReader : Reads[B] =
  (__ \ "stuff").readNullable[Seq[A]].map(_.getOrElse(Seq())).map(B.create)

【讨论】:

实际上它们大约有 20 个字段,但我当然出于这个问题的目的删除了它们。

以上是关于使用 Play-JSON 库解析对象序列的主要内容,如果未能解决你的问题,请参考以下文章

从 json 值解析 JSON 对象字符串

序列化json对象的三种方式

如何使用 Kotlin 序列化解析 JSON 对象列表中的第一个属性?

Gson全解析(上)-Gson基础

url参数解析为一个对象与序列化数据为URL参数

GoLang -- json文件操作