【问题标题】:Play Framework - add a field to JSON objectPlay Framework - 向 JSON 对象添加字段
【发布时间】:2014-05-16 08:22:09
【问题描述】:

我在使用 Scala 向 Play Framework 中的 Json 对象添加字段时遇到问题:

我有一个包含数据的案例类。例如:

case class ClassA(a:Int,b:Int)

我可以使用 Json Writes 创建一个 Json 对象:

val classAObject = ClassA(1,2)
implicit val classAWrites= Json.writes[ClassA]
val jsonObject = Json.toJson(classAObject)

Json 看起来像:

{ a:1, b:2 }

假设我想向 Json 对象添加一个额外的“c”字段。结果:

{ a:1, b:2, c:3 }

如何在不创建新案例类或自己使用 Json.obj 创建 Json 对象的情况下做到这一点?我正在寻找类似的东西:

jsonObject.merge({c:3}) 

任何帮助表示赞赏!

【问题讨论】:

    标签: json scala playframework playframework-2.0


    【解决方案1】:

    更简单的方法是使用 argoanut (http://argonaut.io/)

    var jField : Json.JsonField = "myfield" //Json.JsonField is of type String
    obj1.asJson.->:(jField, obj2.asJson)  // adds a field to obj1.asJson
    

    这里 obj1.asJson 创建一个 JSON 对象 而obj2是要添加到obj1.asJson创建的json中的对象

    【讨论】:

      【解决方案2】:

      JsObject 有一个+ 方法,允许您向对象添加字段,但不幸的是,您的jsonObject 静态类型为JsValue,而不是JsObject。您可以通过多种方式解决此问题。首先是使用as

       scala> jsonObject.as[JsObject] + ("c" -> Json.toJson(3))
       res0: play.api.libs.json.JsObject = {"a":1,"b":2,"c":3}
      

      使用as,你实际上是在向下转换——你是在告诉编译器,“你只知道这是一个JsValue,但相信我,它也是一个JsObject”。在这种情况下这是安全的,但这不是一个好主意。更有原则的做法是直接使用OWrites

      scala> val jsonObject = classAWrites.writes(classAObject)
      jsonObject: play.api.libs.json.JsObject = {"a":1,"b":2}
      
      scala> jsonObject + ("c" -> Json.toJson(3))
      res1: play.api.libs.json.JsObject = {"a":1,"b":2,"c":3}
      

      也许有一天Json 对象将有一个toJsonObject 方法,该方法需要一个OWrites 实例,而这种过于明确的方法就没有必要了。

      【讨论】:

      • 每个签名,Writes.writes 返回JsValue,所以我不明白如何摆脱向上转换(不在 REPL 中)。
      • Tvaroh 是对的,它在我所见的范围内返回 JsValue
      • @elmalto 试试看——classAWrites 将静态输入为OWrites[ClassA](在 Play 2.2 和 2.3 以及 2.10 和 2.11 中)。这是由于 Scala 宏的“未指定但有意”行为(有关详细信息,请参阅我的问题 here)。
      • 为简洁起见跳过类和作者的定义,但这是repl给我的:scala> SessionCreatorWriter.writes(s)res2: play.api.libs.json.JsValue
      • @elmalto 如果你定义一个Writes 实例,你会得到JsValue,但是如果你定义一个OWrites 实例——手动或使用Json.writes 宏,这就是OP 正在做——你会得到一个JsObject
      【解决方案3】:

      我自己找到了解决方案。实际上JsValue,也就是Json.toJson的返回类型没有这个方法,但是JsObject(http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.libs.json.JsObject)有,所以解决方法是:

      val jsonObject = Json.toJson(classAObject).as[JsObject]
      jsonObject + ("c", JsNumber(3)) 
      

      我希望有人会觉得这很有用:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-06-12
        • 2016-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-10
        • 1970-01-01
        相关资源
        最近更新 更多