2012-12-19 9 views
7

Ich habe Code geerbt, der unseren Anwendungsstatus als JSON mit Gson speichert, und liest ihn dann mit fromJson.RuntimeException in Gson beim Parsen von JSON: Fehler beim Aufrufen von protected java.lang.ClassLoader() ohne Argumente

Gson gson = createGson(); 
gson.fromJson(objString, myClass); 

Eines der Felder, die gespeichert werden, ist Location. Leider sehr gelegentlich das Parsen, dass die gespeicherten Daten nicht, weil mein gespeicherten Standort eine mClassLoader in seiner mExtras enthält und die Gson Bibliothek nicht die Classloader mit diesem Fehler zu erstellen:

RuntimeException: Failed to invoke protected java.lang.ClassLoader() with no args

Weiß jemand, warum ein Classloader zu sein, ist in den Extras für meinen Standort enthalten, und ob es in der JSON-Darstellung enden sollte?

Ich gehe davon aus, dass ich das beheben kann, indem ich die Schlüsselfelder aus dem Location-Objekt einzeln speichere (z. B. Längengrad, Breitengrad, Höhe, Zeit, Genauigkeit), aber es wäre nett, wenn möglich das Location-Objekt zu speichern.

Ich sah dort ein ExclusionStrategy Objekt I Felder auszuschließen verwenden könnte, aber ich war nicht sicher, ob ich das verwenden könnte/sollte die Extras aus meinem Ort auszuschließen ...

FYI, ist hier die JSON-Daten für mein Standortobjekt (mit der Länge und Breite verändern mich zu verstecken):

{ 
    <snip> 
    "lastKnownLocation": { 
     "mResults": [ 
      0, 
      0 
     ], 
     "mProvider": "gps", 
     "mExtras": { 
      "mParcelledData": { 
       "mOwnObject": 1, 
       "mObject": 5525040 
      }, 
      "mClassLoader": { 
       "packages": {} 
      }, 
      "mMap": {}, 
      "mHasFds": false, 
      "mFdsKnown": true, 
      "mAllowFds": true 
     }, 
     "mDistance": 0, 
     "mTime": 1354658984849, 
     "mAltitude": 5.199999809265137, 
     "mLongitude": -122.4376, 
     "mLon2": 0, 
     "mLon1": 0, 
     "mLatitude": 37.7577, 
     "mLat1": 0, 
     "mLat2": 0, 
     "mInitialBearing": 0, 
     "mHasSpeed": true, 
     "mHasBearing": false, 
     "mHasAltitude": true, 
     "mHasAccuracy": true, 
     "mAccuracy": 16, 
     "mSpeed": 0, 
     "mBearing": 0 
    }, 
    <snip> 
} 

Hier ist ein Beispiel, was die mExtras enthält, wenn der Code nicht abstürzt:

"mExtras": { 
    "mParcelledData": { 
     "mOwnsNativeParcelObject": true, 
     "mNativePtr": 1544474480 
    }, 
    "mHasFds": false, 
    "mFdsKnown": true, 
    "mAllowFds": true 
} 

Antwort

19

Das Problem besteht darin, dass Sie gerade versuchen, eine vom System bereitgestellte Klasse (Location) in JSON umzuwandeln. Und wie Sie sehen, stoßen Sie auf Probleme mit der Serialisierung von internen State/Java-spezifischen Dingen. JSON ist als semi-generische Methode gedacht, um Informationen weiterzugeben.

Sie können die @Expose Annotation nicht einfach verwenden, da dies nicht Ihre Klasse ist. das würde erfordern, den Quellcode für Location oder über einen ziemlich umfangreichen Prozess modifiziert von ihnen zur Laufzeit mit jassist Zugabe (siehe: http://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime-to.html)

Mit Blick auf die Location Klasse, würde ich einfach eine benutzerdefinierte Gson Serializer und Deserializer erstellen und sein damit gemacht. Was Sie eigentlich interessiert, sind die GPS-Daten, nicht die Interna der Klasse selbst. Sie erstellen einfach den JSON, der die benötigten Informationen enthält, mit den Gettern im Serializer, dann erstellen Sie im Deserializer eine neue Instanz von Location und füllen sie mit den Informationen aus dem mitgelieferten JSON unter Verwendung der öffentlichen Setter.

class LocationSerializer implements JsonSerializer<Location> 
{ 
    public JsonElement serialize(Location t, Type type, 
           JsonSerializationContext jsc) 
    { 
     JsonObject jo = new JsonObject(); 
     jo.addProperty("mProvider", t.getProvider()); 
     jo.addProperty("mAccuracy", t.getAccuracy()); 
     // etc for all the publicly available getters 
     // for the information you're interested in 
     // ... 
     return jo; 
    } 

} 

class LocationDeserializer implements JsonDeserializer<Location> 
{ 
    public Location deserialize(JsonElement je, Type type, 
           JsonDeserializationContext jdc) 
          throws JsonParseException 
    { 
     JsonObject jo = je.getAsJsonObject(); 
     Location l = new Location(jo.getAsJsonPrimitive("mProvider").getAsString()); 
     l.setAccuracy(jo.getAsJsonPrimitive("mAccuracy").getAsFloat()); 
     // etc, getting and setting all the data 
     return l; 
    } 
} 

Jetzt in Ihrem Code verwenden Sie GsonBuilder und registrieren die Klassen:

... 
GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(Location.class, new LocationDeserializer()); 
gsonBuilder.registerTypeAdapter(Location.class, new LocationSerializer()); 
Gson gson = gsonBuilder.create(); 
... 

so ziemlich darum kümmern sollte.

+0

Schöne Antwort, danke. Ich dachte, ich hätte überprüft, ob das Location-Objekt Serializable implementiert, aber es stellt sich heraus, dass es nicht funktioniert - es ist also keine Überraschung, dass unser Code kaputt war! –

+0

Jetzt getestet und die Reparatur funktioniert super. Durch das Speichern der Feldnamen mit den gleichen Namen, die das System verwendet hat ("mProvider", "mAccuracy" usw.), ist es wieder kompatibel mit alten Anwendungsdaten, die das mClassLoader-Extra enthalten, das eine Ausnahme ausgelöst hat. –

+0

Ehrfürchtig. Froh, dass ich helfen konnte. –

2

Betrachten Sie ein benutzerdefiniertes Objekt, das Modell Ihrer Gson, Parsing den Inhalt Objekt pro Objekt und Feld pro Feld

so etwas wie

JSONObject lastKnownLocation = obj.getJSONObject("lastKnownLocation"); 
JSONArray mResults = lastKnownLocation.getJSONArray("mResults"); 

etc... 
MyGSON mg=new MyGSON(lastKnownLocation, mResults etc....); 

So können Sie die volle Kontrolle über die Analyse erhalten zu schaffen, und Wenn Sie einen try \ catch-Block im kritischen mExtra-Teil hinzufügen, können Sie den Block ganz einfach ausschließen oder die Ausnahmebedingung so verwalten, wie Sie möchten.

Verwandte Themen