我有一個虛擬的類Foo
其中有三個成員:爲什麼不是Option [String]類型的成員被序列化?
import play.api.libs.json.Json
case class Foo(id: String, fooType: FooType, nextId: Option[String])
object Foo {
implicit val fooReads = Json.reads[Foo]
implicit val fooFormat = Json.format[Foo]
}
其中作爲
import play.api.libs.json.Json
case class FooType(a: String, b: String)
object FooType {
implicit val fooTypeReads = Json.reads[FooType]
implicit val fooTypeFormat = Json.format[FooType]
}
我發現一些有趣的行爲序列化Foo
對象時FooType
定義。如果我序列化Foo
到JSON,解析JSONified富,我發現,所有的成員都正確解析:
val id = "id"
val fooType = FooType("a", "b")
val nextId = None
val foo = Foo(id, fooType, nextId)
val jsonFoo = Json.toJson(foo)
val parsedFoo = Json.parse(jsonFoo.toString).as[Foo]
assert(parsedFoo == foo)
assert(parsedFoo.id == id)
assert(parsedFoo.fooType == fooType)
assert(parsedFoo.nextId.isEmpty)
這是一件好事,因爲這是我的期望。
然而,在我的下一個測試,我發現nextId
場不序列化都:
val id = "id"
val fooType = FooType("a", "b")
val nextId = None
val foo = Foo(id, fooType, nextId)
val jsonFoo = Json.toJson(foo)
assert((jsonFoo \ "id").as[String] == id)
assert((jsonFoo \ "fooType").as[FooType] == fooType)
assert((jsonFoo \ "nextId").as[Option[String]].isEmpty)
這失敗,出現以下錯誤:
Error:(38, 35) No Json deserializer found for type Option[String]. Try to implement an implicit Reads or Format for this type.
assert((jsonFoo \ "nextId").as[Option[String]].isEmpty)
Error:(38, 35) not enough arguments for method as: (implicit fjs: play.api.libs.json.Reads[Option[String]])Option[String].
Unspecified value parameter fjs.
assert((jsonFoo \ "nextId").as[Option[String]].isEmpty)
同樣地,我發現當我打印由Json.toJson(foo)
轉儲的JSON對象時,JSON對象中缺少nextId
字段:
println(Json.prettyPrint(jsonFoo))
{
"id" : "id",
"fooType" : {
"a" : "a",
"b" : "b"
}
}
但是,我可以解析nextId
字段toOption
;即
assert((jsonFoo \ "nextId").toOption.isEmpty)
如果我的對象其中一個成員本身不能反序列化,我怎樣才能從JSON正確解析對象?
有趣。我可能希望'None'在Play中被序列化爲'null'或'JsNull'對象,但我現在已經看到我必須爲此定義一個自定義作者。感謝您花時間回答! – erip
它只能走一條路。 JSON中缺少的字段或'null'將被映射到'Option',但'Option'只能映射到其他方式之一。設計師選擇忽略該領域是更明智的做法。 –
有道理。只要它能被正確解析,那就沒問題 - 這是關鍵所在。 – erip