提升json操作-在正确的位置添加
考虑以下json:提升json操作-在正确的位置添加,json,scala,lift,lift-json,Json,Scala,Lift,Lift Json,考虑以下json: { "type":"A1", "system":{ "path":"/example.org/FooBar", "lastModified":"2013-10-01T12:00:00Z" }, "fields":{ "foo1":["bar1"], "foo2":["bar2"], "foo3":["bar3"] } } 现在,使用lift json,我想将此json更改为: { "type":"A1",
{
"type":"A1",
"system":{
"path":"/example.org/FooBar",
"lastModified":"2013-10-01T12:00:00Z"
},
"fields":{
"foo1":["bar1"],
"foo2":["bar2"],
"foo3":["bar3"]
}
}
现在,使用lift json,我想将此json更改为:
{
"type":"A1",
"system":{
"path":"/example.org/FooBar",
"lastModified":"2013-10-01T12:00:00Z"
},
"fields":{
"foo1":["bar1"],
"foo2":["bar2"],
"foo3":["bar3"]
},
"injected":{
"bar1":"foo1",
"bar2":"foo2"
}
}
因此,我尝试了以下方法:
scala> val json = parse("""
|{
| "type":"A1",
| "system":{
| "path":"/example.org/FooBar",
| "lastModified":"2013-10-01T12:00:00Z"
| },
| "fields":{
| "foo1":["bar1"],
| "foo2":["bar2"],
| "foo3":["bar3"]
| }
|}""")
json: net.liftweb.json.JValue = JObject(List(JField(type,JString(A1)), JField(system,JObject(List(JField(path,JString(/example.org/FooBar)), JField(lastModified,JString(2013-10-01T12:00:00Z))))), JField(fields,JObject(List(JField(foo1,JArray(List(JString(bar1)))), JField(foo2,JArray(List(JString(bar2)))), JField(foo3,JArray(List(JString(bar3)))))))))
scala> json transform{case JObject(l) => JObject(l ::: List(JField("injected", ("bar1" -> "foo1") ~ ("bar2" -> "foo2"))))}
res0: net.liftweb.json.JsonAST.JValue = JObject(List(JField(type,JString(A1)), JField(system,JObject(List(JField(path,JString(/example.org/FooBar)), JField(lastModified,JString(2013-10-01T12:00:00Z)), JField(injected,JObject(List(JField(bar1,JString(foo1)), JField(bar2,JString(foo2)))))))), JField(fields,JObject(List(JField(foo1,JArray(List(JString(bar1)))), JField(foo2,JArray(List(JString(bar2)))), JField(foo3,JArray(List(JString(bar3)))), JField(injected,JObject(List(JField(bar1,JString(foo1)), JField(bar2,JString(foo2)))))))), JField(injected,JObject(List(JField(bar1,JString(foo1)), JField(bar2,JString(foo2)))))))
scala> Printer.pretty(render(res0))
res1: String =
{
"type":"A1",
"system":{
"path":"/example.org/FooBar",
"lastModified":"2013-10-01T12:00:00Z",
"injected":{
"bar1":"foo1",
"bar2":"foo2"
}
},
"fields":{
"foo1":["bar1"],
"foo2":["bar2"],
"foo3":["bar3"],
"injected":{
"bar1":"foo1",
"bar2":"foo2"
}
},
"injected":{
"bar1":"foo1",
"bar2":"foo2"
}
}
如您所见,注入的部分也被添加到字段
&系统
。
我只想在根下加一次
那么,我做错了什么?如何将json转换为所需的正确结构?您遇到的问题是,在转换中定义的部分函数在json结构中的所有可能级别都匹配。由于外部JObject的“系统”和“字段”组件本身就是JObject,因此它们与部分函数相匹配,并进行了转换
要获得您想要的结果,您需要使匹配更加具体,例如:
json transform {case JObject(fields) if (fields contains JField("type", "A1")) =>
JObject(l ::: ...
使用关于最外层对象的一些唯一信息(这里,它的“type”设置为“A1”)
或者,lift json有一个我没有讨论过的合并功能,但它可能会满足您的需要:
json merge JObject(JField("injected", ...) :: Nil)
如果只需要在单个位置添加字段,transform
并不是最好的工具,您可以直接使用~
:
val newJson = json match {
case obj: JObject =>
obj ~ ("injected" -> ("bar1" -> "foo1") ~ ("bar2" -> "foo2"))
case _ => throw new RuntimeException("Did not receive a JSON object!")
}
如果你知道你总是要解析一个对象,你可以将json
转换成JObject
,避免这里的匹配业务。谢谢!merge工作得很好,它给了我想要的东西。我并不总是使用解析
,它只是为了演示。