我想不出使用组合器的好方法,因为那里的大多数方法都需要一种更直接的方法来将路径中的值映射到案例类字段。
这是一个适用于{"fieldName" : "fieldValue"}.
import play.api.libs.json._
import play.api.data.validation.ValidationError
implicit val fmt: Format[ValueItem] = new Format[ValueItem] {
def reads(js: JsValue): JsResult[ValueItem] = {
js.validate[JsObject].collect(ValidationError("Not a key-value pair")) {
case JsObject(Seq((key, str: JsString))) => ValueItem(key, str.value)
}
}
def writes(v: ValueItem): JsValue = Json.obj(v.key -> v.value)
}
如您所见,我已采用定义reads和手动方式。writes这Reads是棘手的部分,因为我们不习惯将路径名拉入案例类。我们可以validate将对象作为JsObject第一个对象,然后collect只有与我们正在寻找的确切结构匹配的对象(只有一个键值对,其中值为 a JsString)。Writes更直接,因为Json.obj可以做我们想要的。
在行动:
scala> Json.parse(""" { "fieldName" : "fieldValue" } """).validate[ValueItem]
res0: play.api.libs.json.JsResult[ValueItem] = JsSuccess(ValueItem(fieldName,fieldValue),)
scala> val item = ValueItem("myKey", "myValue")
item: ValueItem = ValueItem(myKey,myValue)
scala> Json.toJson(item)
res2: play.api.libs.json.JsValue = {"myKey":"myValue"}