7

次の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を必要な正しい構造に変換できますか?

4

2 に答える 2

6

あなたが抱えている問題は、変換内で定義された部分関数が、json 構造内のすべての可能なレベルで一致することです。外側の JObject の「システム」および「フィールド」コンポーネントはそれ自体が JObject であるため、部分関数と一致し、同様に変換されます。

求めている結果を得るには、一致をより具体的にする必要があります。たとえば、次のようになります。

json transform {case JObject(fields) if (fields contains JField("type", "A1")) =>
   JObject(l ::: ...

最も外側のオブジェクトに関するいくつかの一意の情報を使用します (ここでは、「タイプ」が「A1」に設定されていること)。

あるいは、lift json には、私が扱っていないマージ機能がありますが、必要なものが得られる可能性があります。

json merge JObject(JField("injected", ...) :: Nil)
于 2013-10-01T12:15:28.167 に答える
4

1 か所にフィールドを追加するだけでよい場合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

于 2013-10-01T12:20:52.430 に答える