RuntimeException in Gson parsing JSON: Failed to call protected java.lang.ClassLoader () without arguments

I inherited some code that saves our application state as JSON using Gson and then reads it using fromJson .

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

One of the saved fields is Location . Unfortunately, very rarely does parsing this stored data fail because my saved location includes mClassLoader in its mExtras, and the ClassLoader with this error cannot be created in the Gson library:

RuntimeException: failed to call protected java.lang.ClassLoader () without arguments

Does anyone know why ClassLoader is included in additional parameters for my location and should it end in a JSON view?

I suppose I can fix this by simply saving the key fields from the Location object separately (for example, longitude, latitude, height, time, accuracy), but it would be nice to save the Location object if possible.

I saw that there is an ExclusionStrategy object that I could use to exclude fields, but I was not sure if I could / could use this to exclude extra functions from within my location ...

FYI, here is the JSON data for my location object (with changing longitude and latitude to hide me):

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

Here is an example that contains mExtras when the code does not crash:

 "mExtras": { "mParcelledData": { "mOwnsNativeParcelObject": true, "mNativePtr": 1544474480 }, "mHasFds": false, "mFdsKnown": true, "mAllowFds": true } 
+7
source share
2 answers

The problem is that you are trying to simply convert the system class ( Location ) to JSON. And, as you can see, you are having problems serializing internal states / specific Java things. JSON is understood as a semi-general way of conveying information.

You cannot easily use the @Expose annotation because this is not your class; which will require changing the source code for Location or through a fairly extensive process of adding them at runtime using jassist (see http://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime-to .html )

Looking at the Location class, I would just create a custom Gson serializer and deserializer and do away with it. In fact, you are interested in GPS data, not the internal elements of the class itself. You simply create a JSON containing the necessary information in the serializer using getters, and then in Deserializer you create a new instance of Location and fill it with information from the provided JSON using public setters.

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

Now in your code you use GsonBuilder and register the classes:

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

That should pretty much take care of this.

+19
source

Consider creating a custom object that simulates your GSON, analyzing the contents of an object into an object and field in a field

something like

 JSONObject lastKnownLocation = obj.getJSONObject("lastKnownLocation"); JSONArray mResults = lastKnownLocation.getJSONArray("mResults"); etc... MyGSON mg=new MyGSON(lastKnownLocation, mResults etc....); 

This way you can take complete control of the parsing and add a try / catch block to the critical part of mExtra, you can easily exclude the block or control the exception as you wish.

+2
source

All Articles