2016-05-16 7 views
1

ich eine generische Karte haben, die eine Liste von Karten enthalten können, die iterativ eine weitere Liste von Karten oder eine andere Karte des Objekts enthalten können usw.iterativ Traverse n Menge von verschachtelten Karten und Listen

Karte mymap;

Ich brauche einen Weg, ohne die Struktur der Karte zu kennen, um einen verschachtelten Wert zu aktualisieren. Zum Beispiel sagen, dass meine Karte wie folgt aussieht:

{mymap : myList[{'myObject' : 'someValue'}, {'myObject' : 'someOtherValue'}]} 

Basierend auf irgendeine Art von Pfadausdruck wie ‚mymap.myList.myObject‘ Ich muss in der Lage, alle ‚myObject Werte mit einem neuen Wert zu ersetzen.

Wie kann ich iterativ alle Maps und Listen durchlaufen, um zu den gewünschten Werten zu gelangen? Dies muss generisch sein, damit sich die Struktur der Map ändern kann und ich basierend auf einem Pfadausdruck iteriere.

+0

Sie möchten die Schlüssel in einer Karte durch neue Objekte ersetzen? Oder mit _a_ neuem Objekt? – CPerkins

+0

Ich möchte den Wert eines bestimmten Schlüssels durch einen neuen Wert ersetzen. –

+0

also auf der Grundlage des obigen Beispiels möchte ich alle Vorkommen von 'myObject' durch einen neuen Wert ersetzen. –

Antwort

1

JsonPath könnte passen. Stellen Sie sicher, dass Sie diese beiden Abhängigkeiten auf Ihrem Klassenpfad haben:

com.jayway.jsonpath:json-path:2.2.0 
com.fasterxml.jackson.core:jackson-databind:2.7.0 

Und dann:

import java.util.*; 
import com.jayway.jsonpath.JsonPath; 

public class Sandbox { 

    private static class Widget { 
     private final String id; 

     public Widget(String id) { 
      this.id = id; 
     } 

     @Override 
     public String toString() { 
      return "Widget{id='" + id + "'}"; 
     } 
    } 

    @SuppressWarnings("unchecked") 
    public static void main(String[] args) { 
     Map map1 = new HashMap(); 
     map1.put("myObject", new Widget("cog")); 

     Map map2 = new HashMap(); 
     map2.put("myObject", new Widget("sprog")); 

     Map root = new HashMap(); 
     root.put("myList", new ArrayList(Arrays.asList(map1, map2))); 
     root.put("myObject", new Widget("frobulator")); 

     System.out.println("BEFORE: " + root); 

     // set the value of all 'myObject' nodes no matter how deeply nested 
     JsonPath.parse(root).set("$..myObject", new Widget("novaDetonator")); 

     System.out.println("AFTER:" + root); 
    } 
} 

Ausgang:

BEFORE: {myList=[{myObject=Widget{id='cog'}}, {myObject=Widget{id='sprog'}}], myObject=Widget{id='frobulator'}} 
2016-05-16 13:44:44,337 [main] DEBUG com.jayway.jsonpath.internal.path.CompiledPath - Evaluating path: $..['myObject'] 
2016-05-16 13:44:44,343 [main] DEBUG com.jayway.jsonpath.internal.JsonContext - Set path $['myObject'] new value Widget{id='novaDetonator'} 
2016-05-16 13:44:44,344 [main] DEBUG com.jayway.jsonpath.internal.JsonContext - Set path $['myList'][0]['myObject'] new value Widget{id='novaDetonator'} 
2016-05-16 13:44:44,344 [main] DEBUG com.jayway.jsonpath.internal.JsonContext - Set path $['myList'][1]['myObject'] new value Widget{id='novaDetonator'} 
AFTER:{myList=[{myObject=Widget{id='novaDetonator'}}, {myObject=Widget{id='novaDetonator'}}], myObject=Widget{id='novaDetonator'}} 

Natürlich Ihr Neuwert ein String anstelle eines sein könnte Widget; Es ist ordentlich, dass JsonPath mit beiden zusammenarbeiten kann.

Verwandte Themen