2016-02-03 9 views
5

Ich verstehe nicht, warum die letzte Zeile dieses Codes eine leere Zeichenfolge zurückgibt.javax.json seltsames Verhalten

Map<String, JsonObjectBuilder> HASH_MAP = new HashMap<>(); 

JsonObjectBuilder one = Json.createObjectBuilder(); 
one.add("test1","test1"); 
HASH_MAP.put("one", one); 

JsonObjectBuilder two = Json.createObjectBuilder(); 
two.add("test2","test2"); 
HASH_MAP.put("two", two); 

JsonObjectBuilder toReturn = Json.createObjectBuilder(); 
JsonArrayBuilder l1 = Json.createArrayBuilder(); 
for (Map.Entry<String, JsonObjectBuilder> l : HASH_MAP.entrySet()) { 
    l1.add(l.getValue()); 
} 

toReturn.add("l1", l1); 
toReturn.add("otherParam", "value2"); 
String strJSON = toReturn.build().toString(); 
System.out.println("JSON1: " + strJSON); 
System.out.println("JSON2: " + HASH_MAP.get("one").build().toString()); 

Dies ist die Ausgabe:

Info: JSON1: {"l1":[{"test1":"test1"},{"test2":"test2"}],"otherParam":"value2"} 
Info: JSON2: {} 

Ich espetting, dass die zweite JSON {"test1":"test1"} ist. Ich habe mich geirrt?
Das Problem scheint, Verbindung mit der .build() Funktion zu sein, die alle valueMap Elemente, die zu HASH_MAP hinzugefügt werden, auf Null setzt (sehen Sie das Bild). enter image description here

Wie kann ich den Wert innerhalb der HASH_MAP unberührt lassen?

+0

versuchen, das zu testen: setzen Sie Ihre System.out .println ("JSON2:" + HASH_MAP.get ("eins"). build(). toString()); nach der Zeile HASH_MAP.put ("eins", eins); –

+0

Dies ist die Ausgabe: JSON: {"test1": "test1"} # JSON: {"l1": [{}, {"test2": "test2"}], "otherParam": "value2"} # JSON : {} – user72708

Antwort

4

Nach build() eine JsonObject von einem JsonObjectBuilder ing der Erbauer ist gelöscht zur Wiederverwendung bereit zu sein. Um dies zu verdeutlichen:

JsonObjectBuilder b = Json.createObjectBuilder(); 
b.add("foo", "bar"); 
JsonObject o = b.build(); 
JsonObject p = b.build(); 
System.out.println(o.toString()); // {"foo":"bar"} 
System.out.println(p.toString()); // {} 

Wenn Sie das tun

l1.add(l.getValue()); // l.getValue() is (JsonObjectBuilder) one at some time 

build() genannt wird implizit auf one, daher ist es entleert.

Dann hier:

System.out.println("JSON2: " + HASH_MAP.get("one").build().toString()); 

Sie die Darstellung eines leeren JsonObject bauen. statt JsonObjectBuilders in Ihrem hashmap

Um dies zu migitate, Sie zum Beispiel Speicher JsonObjects könnte:

Map<String, JsonObject> HASH_MAP = new HashMap<>(); 

JsonObjectBuilder one = Json.createObjectBuilder(); 
one.add("test1","test1"); 
HASH_MAP.put("one", one.build()); 

JsonObjectBuilder two = Json.createObjectBuilder(); 
two.add("test2","test2"); 
HASH_MAP.put("two", two.build()); 

JsonObjectBuilder toReturn = Json.createObjectBuilder(); 
JsonArrayBuilder l1 = Json.createArrayBuilder(); 
for (Map.Entry<String, JsonObject> l : HASH_MAP.entrySet()) { 
    l1.add(l.getValue()); 
} 

toReturn.add("l1", l1); 
toReturn.add("otherParam", "value2"); 
String strJSON = toReturn.build().toString(); 
System.out.println("JSON1: " + strJSON); 
System.out.println("JSON2: " + HASH_MAP.get("one").toString()); 

Jetzt sollte es funktionieren wie erwartet.

3

Beachten Sie, dass der Aufruf von build() den Wert in Ihrem Objekt one JSonObjectBuilder gespeichert spülen, so dass Sie nur einmal die Methode Build() aufrufen, wenn Sie es erneut aufrufen Sie die Darstellung eines leeren JSonObject haben gehen . Ex:

one.add("test1","test1"); 
System.out.println(one.build()) 
System.out.println(one.build()) 

die Ausgabe:

{"test1":"test1"} 
{} 

Wenn Sie es wirklich wollen wieder anrufen, haben Sie wieder den Wert hinzufügen, die Sie wollen. Ex:

one.add("test1","test1"); 
System.out.println(one.build()) 
one.add("test1","test1") 
System.out.println(one.build()) 

die Ausgabe:

{"test1":"test1"} 
{"test1":"test1"} 

Wie @Ctx sagt, könnten Sie in Ihrer Karte JsonObjects statt JsonObjectBuilders setzen, so setzt als Wert Ihrer Karte der JsonObject durch den Aufruf von dem zurück Methode build().

Ex:

HASH_MAP.put("one", one.build()); 
0

Wie bereits beantwortet, die bereitgestellte Implementierung von JsonObjectBuilder Wallungen, wenn Sie Build() aufrufen.

Die beste Lösung ist Ihre eigene, nicht-Spülung Builder zu implementieren, auf der Grundlage der JsonObjectBuilder Schnittstelle:

public final class NfJsonObjectBuider implements JsonObjectBuilder { 

    private Map<String, Object> values = new LinkedHashMap<>(); 

    @Override 
    public JsonObjectBuilder add(String name, JsonValue value) { 
     this.values.put(name, value); 
     return this; 
    } 

    @Override 
    public JsonObjectBuilder add(String name, String value) { 
     this.values.put(name, value); 
     return this; 
    } 

    @Override 
    public JsonObjectBuilder add(String name, BigInteger value) { 
     this.values.put(name, value); 
     return this; 
    } 
    //other add(...) methods with the same implementation 

    @Override 
    public JsonObject build() { 
     //HERE: reuse their building logic. 
     final JsonObjectBuilder builder = Json.createObjectBuilder(); 
     for(final Entry<String, Object> pair : this.values.entrySet()) { 
      this.addToBuilder(pair, builder); 
     } 
     return builder.build(); 
    } 

    private void addToBuilder(Entry<String, Object> pair, JsonObjectBuilder 
builder) { 
     if(pair.getValue() instanceof JsonValue) { 
      builder.add(pair.getKey(), (JsonValue) pair.getValue()); 
     } 
     if(pair.getValue() instanceof String) { 
      builder.add(pair.getKey(), (String) pair.getValue()); 
     } 
     if(pair.getValue() instanceof Boolean) { 
      builder.add(pair.getKey(), (Boolean) pair.getValue()); 
     } 
     //A couuple more ifs to cover all the add(...) methods. 
    } 
} 

Der ganze Artikel hier: http://www.amihaiemil.com/2017/06/14/non-flushable-jsonobjectbuilder.html

+0

Es wird dringend empfohlen, Ihre gesamte Lösung hierher zu bringen, da die Links kaputt gehen. – yakobom