Play框架 - 在JSON对象中添加一个字段

42

我需要在使用Scala的Play框架中添加Json对象字段,但遇到了问题:

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

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 }
我该如何做到这一点,而不创建一个新的case类或自己使用Json.obj创建我的Json对象?我正在寻找像这样的东西:
jsonObject.merge({c:3}) 

感谢任何帮助!

3个回答

49

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
2
@elmalto 试一下吧 - classAWrites 将被静态类型化为 OWrites[ClassA](在 Play 2.2 和 2.3 上以及在 2.10 和 2.11 上)。这是由于 Scala 宏的“未指定但预期”行为所致(有关详细信息,请参见我的问题此处)。 - Travis Brown
1
@elmalto 如果你定义了一个Writes实例,你会得到JsValue,但如果你手动定义了一个OWrites实例或使用Json.writes宏(这就是OP正在做的),你会得到一个JsObject - Travis Brown
实际上不需要括号。这样也可以:jsobj + "key" -> entity.key - Wrench
@Wrench 那个做的完全不同。+-具有相同的优先级,因此括号绝对是必要的。 - Travis Brown
显示剩余4条评论

8

-1

更简单的方法是使用Argonaut(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中的对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接