2016-02-03 13 views
5

Nie rozumiem, dlaczego ostatni wiersz tego kodu zwraca pusty ciąg znaków.dziwne zachowanie javax.json

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()); 

To wyjście:

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

ja espetting że drugi JSON jest {"test1":"test1"}. Jestem w błędzie?
Problem wydaje się być łączem z funkcją .build(), która ustawia wszystkie wartości wartościMap elementów dodanych do HASH_MAP na wartość null (patrz zdjęcie). enter image description here

W jaki sposób mogę pozostawić wartość wewnątrz HASH_MAP nietkniętą?

+0

spróbuj przetestować że: umieścić swoje System.out .println ("JSON2:" + HASH_MAP.get ("one"). build(). toString()); po linii HASH_MAP.put ("jeden", jeden); –

+0

To jest wynik: JSON: {"test1": "test1"} # JSON: {"l1": [{}, {"test2": "test2"}], "innyParam": "wartość2"} # JSON : {} – user72708

Odpowiedz

4

Po build() ing JsonObject z JsonObjectBuilder budowniczym jest wyczyszczone być gotowy do ponownego użycia. Aby to zilustrować:

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()); // {} 

Kiedy robisz

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

build() nazywa niejawnie na one, stąd jest opróżniany.

Następnie tutaj:

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

budować reprezentację pustym JsonObject.

Aby to migitate, można na przykład sklepowych JsonObjects zamiast JsonObjectBuilders w swojej hashmap:

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()); 

Teraz powinno działać zgodnie z oczekiwaniami.

3

Należy pamiętać, że wezwanie do build() przepłukać wartość przechowywaną w obiekcie one JSonObjectBuilder, więc można wywołać tylko raz kompilacja metoda() Jeśli zadzwonisz ponownie udać się mieć reprezentację pustym JSonObject . Ex:

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

wyjście:

{"test1":"test1"} 
{} 

Jeśli naprawdę chcesz się połączyć go ponownie, trzeba ponownie dodać wartości, które chcesz. Ex:

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

wyjście:

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

Jak mówi @Ctx, można umieścić w swoim map JsonObjects zamiast JsonObjectBuilders, więc umieścić jako wartość swojej mapie JSONObject zwrócony przez wezwanie metoda build().

Ex:

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

Jak już odpowiedział dostarczona realizacja uderzenia JsonObjectBuilder kiedy zadzwonić build().

Najlepszym rozwiązaniem jest wprowadzenie własnego, bez spłukiwania konstruktora, oparte na interfejsie JsonObjectBuilder:

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

Cały artykuł tutaj: http://www.amihaiemil.com/2017/06/14/non-flushable-jsonobjectbuilder.html

+0

Zaleca się zabranie ze sobą całego rozwiązania, linki się zepsują. – yakobom