2017-02-16 4 views
0

Ich habe einen JSON, das wie folgt aussieht:Wie Liste von Listen analysieren Gson mit

{ 
    "1": [{"id": 1}, {"id": 2},{"id": 3}, {"id": 4}], 
    "2": [{"id": 5}, {"id": 6}], 
    "3": [{"id": 3}, {"id": 4}] 
} 

Ich möchte es in

List<List<Integer>> list 

oder

Map<Integer, List<Integer>> map 

Wie analysiert werden Soll ich Gson verwenden, um dies zu erreichen?

Antwort

0

Sie haben mindestens zwei Optionen: Imperativ und der Gson Weg.

In der Imperativ Option, können Sie einfach die ganze JSON Baum für den gegebenen JSON parsen mit Gson Einrichtungen Schritt für Schritt:

final Gson gson = new GsonBuilder() 
     // any custom Gson configuration here 
     .create(); 
final Map<Integer, List<Integer>> map = new LinkedHashMap<>(); 
for (final Entry<String, JsonElement> e : gson.fromJson(JSON, JsonElement.class).getAsJsonObject().entrySet()) { 
    // parseInt() ignores additional type adapters in Gson 
    final Integer key = gson.fromJson(e.getKey(), Integer.class); 
    final List<Integer> list = new ArrayList<>(); 
    @SuppressWarnings({ "unchecked", "rawtypes" }) 
    final Iterable<JsonObject> asJsonArray = (Iterable) e.getValue().getAsJsonArray(); 
    for (final JsonObject el : asJsonArray) { 
     final Integer integer = gson.fromJson(el.get("id"), Integer.class); 
     list.add(integer); 
    } 
    map.put(key, list); 
} 
out.println(map); 

Ein bisschen schmutzig, ist es nicht ?. Der Ausgang:

{1 = [1, 2, 3, 4], 2 = [5, 6], 3 = [3, 4]}

Eine Alternative macht eine individuelle gefälschte DTO, die eine spezielle Markierung für Gson TypeToken s wäre, um JSON-Deserialisierung genauer zu binden. Zum Beispiel:

Dies ist eine abstrakte Klasse mit einem privaten Konstruktor, der einen Fehler verursacht, so dass er nicht extern instanziiert werden kann. Und es sollte nie sein, es ist nur ein Marker.

final class FakeIntDeserializer 
     implements JsonDeserializer<Integer> { 

    private static final JsonDeserializer<Integer> fakeIntDeserializer = new FakeIntDeserializer(); 

    private FakeIntDeserializer() { 
    } 

    static JsonDeserializer<Integer> getFakeIntDeserializer() { 
     return fakeIntDeserializer; 
    } 

    @Override 
    public Integer deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) { 
     final JsonElement idElement = json.getAsJsonObject().get("id"); 
     return context.deserialize(idElement, Integer.class); 
    } 

} 

Diese Deserialisierer sind die JSON Array-Elemente bekannt, die id Eigenschaft aufweisen: sobald es von dem übergeordneten Objekt erhalten wird, ist die idElement einen nachgeschalteten Parser einen delegierte Integer Wert zu extrahieren. Obwohl es möglich ist, idElement.getAsInt() zu verwenden, wird idElement delegiert, um die gesamte Gson Konfiguration zu respektieren (Sie können spezielle Regeln für die Klasse Integer haben). Und wie die gefälschte DTO-Klasse und ihre JSON Deserializer arbeiten zusammen:

final Type integerToFakeIntListType = new TypeToken<Map<Integer, List<FakeInt>>>() { 
}.getType(); 
final Gson gson = new GsonBuilder() 
     .registerTypeAdapter(FakeInt.class, getFakeIntDeserializer()) 
     .create(); 
final Map<Integer, List<Integer>> map = gson.fromJson(JSON, integerToFakeIntListType); 
out.println(map); 

Beachten Sie, dass die Gson Instanz mit einer Art von einem Hack oder ein Betrüger gebaut: die FakeInt Klasse der benutzerdefinierten Deserializer gebunden ist, die nur Rückkehr Integer Werte oder null. Sobald die Typen und ihre Deserialisierer gebunden sind, ist die Gson Instanz bereit zu verwenden und der angegebene JSON kann geparst werden , als ob es eine Zuordnung von ganzen Zahlen zu Listen von ganzen Zahlen wäre. Genau die gleiche Ausgabe wie folgt:

{1 = [1, 2, 3, 4], 2 = [5, 6], 3 = [3, 4]}

Verwandte Themen