2014-04-04 36 views
29

我有个问题与使用的Scala在播放框架添加一个字段,JSON对象:播放框架 - 将字段添加到JSON对象

我有一个包含数据的情况下类。例如:

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

,我能够创建使用JSON 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}) 

任何帮助赞赏!

回答

31

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实例,这种过于明确的做法没有必要。

+0

每签名创建的JSON对象,'写道。写'返回'JsValue',所以我不明白你如何摆脱upcasting(不在REPL中)。 – Tvaroh

+0

Tvaroh是正确的,它返回JsValue,据我所见 – elmalto

+2

@elmalto试试吧''classAWrites'将静态类型为'OWrites [ClassA]'(在Play 2.2和2.3以及2.10和2.11中)。这是由于Scala宏的“未指定但意图”的行为(请参阅我的问题[here](http:// stackoverflow。com/q/13669974/334519)以获得详细信息)。 –

-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