2013-10-01 19 views
6

die folgende json betrachten:Lift-json Manipulation - Hinzufügen an der richtigen Stelle

{ 
    "type":"A1", 
    "system":{ 
    "path":"/example.org/FooBar", 
    "lastModified":"2013-10-01T12:00:00Z" 
    }, 
    "fields":{ 
    "foo1":["bar1"], 
    "foo2":["bar2"], 
    "foo3":["bar3"] 
    } 
} 

jetzt, Lift-json mit, ich will in diese json ändern:

{ 
    "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" 
    } 
} 

so, i folgendes versucht:

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" 
    } 
} 

und wie Sie sehen können, die injected Teil wurde in fields hinzugefügt & system als auch. Ich wollte es nur einmal unter der Wurzel hinzufügen.

also, was mache ich falsch? und wie kann ich den JSON in die richtige Struktur umwandeln, die ich brauche?

Antwort

5

Das Problem, das Sie haben, ist, dass die Teilfunktion, die in der Transformation definiert ist, auf allen möglichen Ebenen innerhalb der JSON-Struktur übereinstimmt. Da die Komponenten "system" und "fields" des äußeren JObject selbst JObjects sind, stimmen sie mit der partiellen Funktion überein und werden ebenfalls transformiert.

das Ergebnis erhalten Sie suchen, müssen Sie das Spiel präziser machen, zB:

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

einige einzigartigen Informationen über den äußersten Gegenstand (hier, dass es „type“ muss gesetzt "A1").

Alternativ hat Lift json eine Merge-Funktion, die ich nicht behandelt habe, die aber vielleicht geben, was Sie wollen:

json merge JObject(JField("injected", ...) :: Nil) 
+0

danke! Merge funktionierte großartig und gab mir genau das, was ich wollte. –

4

Wenn Sie nur ein Feld an einem einzigen Ort hinzufügen müssen, transform isn‘ t das beste Werkzeug-Sie können ~ nur statt:

val newJson = json match { 
    case obj: JObject => 
    obj ~ ("injected" -> ("bar1" -> "foo1") ~ ("bar2" -> "foo2")) 
    case _ => throw new RuntimeException("Did not receive a JSON object!") 
} 

Wenn Sie für eine Tatsache, dass Sie immer ein Objekt analysieren werde, Sie json zu JObject und vermeiden das passende Unternehmen hier werfen könnte.

+0

ich benutze nicht immer 'parse', es war nur für die Demonstration. –