2016-02-03 21 views
5

Non capisco perché l'ultima riga di questo codice restituisca una stringa vuota.javax.json strano comportamento

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

Questa è l'uscita:

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

sto espetting che il secondo JSON è {"test1":"test1"}. Ho sbagliato?
Il problema sembra essere il collegamento con la funzione .build() che imposta tutto il valore Mappa di elementi aggiunti a HASH_MAP su null (vedere l'immagine). enter image description here

Come posso lasciare intatto il valore all'interno di HASH_MAP?

+0

tenta di verificare che: mettere lo System.out .println ("JSON2:" + HASH_MAP.get ("uno"). build(). toString()); dopo la riga HASH_MAP.put ("uno", uno); –

+0

Questo è l'output: JSON: {"test1": "test1"} # JSON: {"l1": [{}, {"test2": "test2"}], "otherParam": "value2"} # JSON : {} – user72708

risposta

4

Dopo build() ing un JsonObject da un JsonObjectBuilder costruttore viene cancellata per essere pronti per il riutilizzo. Per illustrare questo:

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

Quando si esegue

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

build() è chiamato implicitamente su one, quindi è svuotato.

Poi qui:

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

a costruire la rappresentazione di un vuoto JsonObject.

Per migitate questo, si potrebbe ad esempio memorizzare JsonObjects invece di JsonObjectBuilders nel 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()); 

ora, dovrebbe funzionare come previsto.

3

Tenete a mente che la chiamata a build() lavare il valore memorizzato nel vostro oggetto one JSonObjectBuilder, in modo da poter chiamare una sola volta il metodo build(), se si chiama ancora una volta si va per avere la rappresentazione di un vuoto JSonObject . Es:

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

l'output:

{"test1":"test1"} 
{} 

Se davvero si vuole chiamarlo di nuovo, è necessario aggiungere ancora una volta il valore che si desidera. Es:

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

l'output:

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

Come dice @Ctx, si potrebbe mettere nella mappa JsonObjects invece di JsonObjectBuilders, così si può mettere come valore della vostra mappa del JsonObject restituito dalla chiamata del metodo build().

Es:

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

Come già risposto, l'attuazione prevista delle vampate JsonObjectBuilder quando si chiama build().

La soluzione migliore è quella di implementare il proprio, costruttore non vampate di calore, basata sull'interfaccia 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. 
    } 
} 

L'intero articolo qui: http://www.amihaiemil.com/2017/06/14/non-flushable-jsonobjectbuilder.html

+0

Si consiglia vivamente di portare qui l'intera soluzione, i collegamenti si rompono. – yakobom