我在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"
}
}
是否有正确的方法来执行此展平和取消展开,而不使用单独的Reads
和Writes
对象?我的实际数据结构非常大(虽然不是太复杂),所以简洁性很好。
答案 0 :(得分:2)
如果我理解正确,您可以/应该以常规方式创建您的格式:
(__ \ "id").format[String] and
(__ \ "data").format(
(__ \ "foo").format[String] and
(__ \ "bar").format[String]
tupled
)
然后只提供不同的apply
和unapply
方法。
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))