【问题标题】:lift-json manipulation - adding in the right placeLift-json 操作 - 在正确的位置添加
【发布时间】:2013-10-01 11:52:53
【问题描述】:

考虑以下 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",
  "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"
  }
}

如您所见,injected 部分也已添加到 fieldssystem 中。 我只是想在根目录下添加一次。

那么,我做错了什么?以及如何将 json 转换为我需要的正确结构?

【问题讨论】:

    标签: json scala lift lift-json


    【解决方案1】:

    您遇到的问题是在 transform 中定义的部分函数在 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)
    

    【讨论】:

    • 谢谢!合并效果很好,给了我想要的东西。
    【解决方案2】:

    如果你只需要在一个地方添加一个字段,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 并避免这里的匹配业务。

    【讨论】:

    • 我并不总是使用parse,只是为了演示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    相关资源
    最近更新 更多