2

给定以下案例类:

case class ValueItem(key: String, value: String)

和以下 json 格式化程序:

implicit val valueItemFormat: Format[ValueItem] = (
        (__ \ "key").format[String] and
        (__ \ "value").format[String])(ValueItem.apply, unlift(ValueItem.unapply))

ValueItem 实例的 json 表示形式,例如

ValueItem("fieldname", "fieldValue")

{ "key" : "fieldName" , "value" : "fieldValue" }

我想知道如何在平面键/值序列化中获取 json,例如

{ "fieldName" : "fieldValue" }
4

2 回答 2

1

我想不出使用组合器的好方法,因为那里的大多数方法都需要一种更直接的方法来将路径中的值映射到案例类字段。

这是一个适用于{"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和手动方式。writesReads是棘手的部分,因为我们不习惯将路径名拉入案例类。我们可以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"}
于 2015-05-09T13:24:05.990 回答
0

Play 发布了它的模块,用于处理独立于 Play 框架的 JSON,Play WS

发表了一篇关于将 JSON 读取到案例类的博客文章,但 write 非常相似。在http://pedrorijo.com/blog/scala-json/上查看

使用案例类和Play WS(已包含在 Play 框架中),您可以使用简单的单行隐式在 json 和案例类之间进行案例转换

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)

object User {
  implicit val userJsonFormat = Json.format[User]
}
于 2016-01-05T20:38:03.480 回答