Play 2.1 Scala - JSON - 具有嵌套数据结构的对称格式对象,无法正确序列化

时间:2013-02-15 14:28:06

标签: json scala playframework-2.1

我在Play 2.1 Scala中为某些JSON编写Format对象时遇到了一些麻烦。我的(大大简化)JSON看起来像这样:

{
  "id": "id-1",
  "data": {
    "foo": "teststr1",
    "bar": "teststr2"
  }
}

我想将其序列化/反序列化为稍微简单,扁平化的格式:

case class TestData(id: String, foo: String, bar: String)

我最初的尝试看起来像这样:

implicit val testCaseFormat: Format[TestData] = (
  (__ \ "id").format[String] and
  (__ \ "data" \ "foo").format[String] and
  (__ \ "data" \ "bar").format[String]
)(TestData.apply, unlift(TestData.unapply))

读取数据时工作正常,但在输出JSON中只存在最后一个“数据”值(bar)时,可能是因为data个对象正在为每个后续值覆盖:

{
   "id" : "id-1",
   "data":{
     "bar":"teststr2"
   }
 }

是否有正确的方法来执行此展平和取消展开,而不使用单独的ReadsWrites对象?我的实际数据结构非常大(虽然不是太复杂),所以简洁性很好。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,您可以/应该以常规方式创建您的格式:

(__ \ "id").format[String] and
(__ \ "data").format(
  (__ \ "foo").format[String] and
  (__ \ "bar").format[String]
  tupled
)

然后只提供不同的applyunapply方法。

def specialApply(data:(String, (String, String))) = {
  val(id, (foo, bar)) = data
  TestData(id, foo, bar)
}

def specialUnapply(data:TestData):Option[(String, (String, String))] =
  Option(data) map { testData =>
    (testData.id, (testData.foo, testData.bar))
  }

修改

您可以通过组合apply和unapply方法来避免将方法添加到协同对象:

implicit val testCaseFormat: Format[TestData] = (
    // ...
)(TestData.tupled.compose { data:(String, (String, String)) => 
    val (id, (foo, bar)) = data
    (id, foo, bar)
  }), unlift(TestData.unapply))