2016-12-12 2 views
0

Ich habe Probleme mit der Serialisierung von JSON-Daten.Gson wird in eine LinkedTreeMap gelesen

Also, ich versuche zu Generika zu verwenden, aber irgendwie hasst Gson mich, wenn ich versuche, es zu implementieren. Alles, was ich versuche, ist eine grundlegende Abstraktion mit Generika. Hier ist mein Code:

Hauptklasse, die den Generika Teil tut:

package com.yasinyazici.riot.config.json; 

import com.google.gson.Gson; 
import com.google.gson.reflect.TypeToken; 
import java.lang.reflect.Type; 
import java.util.Map; 

public abstract class JsonDataParser<T> { 
    protected Gson gson = new Gson(); 
    protected String json; 

    public JsonDataParser(String json) { 
     this.json = json; 
    } 

    protected Map<String, T> transform() { 
     Type type = new TypeToken<Map<String, T>>(){}.getType(); 
     return gson.fromJson(json, type); 
    } 

    public abstract T get(); 
} 

Hier ist ein Kind der Hauptklasse ist:

package com.yasinyazici.riot.config.json.impl; 

import com.yasinyazici.riot.config.json.JsonDataParser; 
import com.yasinyazici.riot.data.summoner.SummonerProperties; 

public class SummonerPropertiesParser extends JsonDataParser<SummonerProperties> { 
    public SummonerPropertiesParser(String json) { 
     super(json); 
    } 

    @Override 
    public SummonerProperties get() { 
     transform().entrySet().forEach(p -> System.out.println(p.getValue().getProfileIconId())); 
     return null; 
    } 
} 

Wie Sie sehen können, IntelliJ erkennt sogar # get() als "SummonerProperties".

Das ist mein Fehler ist:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.yasinyazici.riot.data.summoner.SummonerProperties 
    at com.yasinyazici.riot.config.json.impl.SummonerPropertiesParser.lambda$get$0(SummonerPropertiesParser.java:17) 
    at java.lang.Iterable.forEach(Iterable.java:75) 
    at com.yasinyazici.riot.config.json.impl.SummonerPropertiesParser.get(SummonerPropertiesParser.java:17) 
    at com.yasinyazici.riot.Main.main(Main.java:16) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 

Ich bin ein bisschen verwirrt. Wenn ich p (das Objekt selbst) zu drucken, erhalte ich die json in einigen seltsamen Format

jungleíslife={id=8.2249757E7, name=Jungle ís Life, profileIconId=1339.0, summonerLevel=30.0, revisionDate=1.481558959E12} 

Original-json wie folgt aussieht:

{"jungleíslife":{"id":82249757,"name":"Jungle ís Life","profileIconId":1339,"summonerLevel":30,"revisionDate":1481558959000}} 

p # getValue() druckt den Körper des json. (in dem seltsamen Format)

So scheint es, als würde etwas nicht richtig geparst werden.

Jeder? Würde jede Art von Hilfe/Lösung schätzen.

EDIT: Dies ist kein exaktes Duplikat, Grund dafür ist, dass ich nicht versuche, einen beliebigen Typ zu parametrisieren, sondern den ursprünglichen Typ zu erhalten (ich verwende keine Klassenvariable für den Zugriff auf a Klassen Felder für das Parsing, will ich auch nicht).

EDIT2: In Ordnung, okay. Erm, ich versuchte, das Beispiel mit Option 1 (siehe verlinkte Frage als Referenz), aber ich bekomme den folgenden (Geist, machte ich die Methode #getRawType() in ListParameterizedType Klasse Rückkehr Map.class):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 

Selbst wenn ich es Arraylist zurückkehrt halten, wirft es mir diese:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ 

EDIT: Noch Probleme bekam, dass mit ..

EDIT2: Hat NIEMAND eine mögliche Lösung ..?

+0

Daher die Bearbeitung, bitte aufhören zu spammen die "als Duplikat markieren" -Button und eher mich mit einigen tatsächlichen Informationen. – Sh0ck

+0

Wie das Duplikat erklärt, wird dieser 'neue TypeToken >() {}. GetType()' niemals so funktionieren, wie Sie es wollen. Gson weiß nicht, welchen Typ Sie eigentlich für 'T' meinen, also verwendet es seine Standardwerte. Für JSON-Objekte ist das "LinkedTreeMap". –

+0

@SotiriosDelimanolis siehe zur Referenz bearbeiten – Sh0ck

Antwort

1

Sie müssen den TypeToken in der Unterklasse konstruieren, wo die konkreten Typinformationen verfügbar sind.Fügen Sie eine abstrakte Methode der Superklasse:

protected abstract Type getType(); 

Ändern der Parse-Methode, es zu benutzen:

protected Map<String, T> transform() { 
    return gson.fromJson(json, getType()); 
} 

Dann getType in der Unterklasse überschreiben die konkreten Typ zurückzukehren:

@Override 
protected Type getType() { 
    return new TypeToken<Map<String, SummonerProperties>>(){}.getType(); 
} 

Unrelated , aber das "seltsame Format", das Sie sehen, wenn Sie getValue() drucken, ist nicht json, es ist von Object.toString().

+0

Oh mein Gott, die Lösung war so einfach, wie könnte ich nicht daran denken? Ich danke dir sehr !!! – Sh0ck

Verwandte Themen