RuntimeException в Gson parsing JSON: Не удалось вызвать защищенный java.lang.ClassLoader () без аргументов

Я унаследовал некоторый код, который сохраняет наше состояние приложения как JSON с помощью Gson, а затем читает его, используя fromJson .

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

Одним из сохраненных полей является местоположение . К сожалению, очень редко анализ этих сохраненных данных терпит неудачу, потому что мое сохраненное местоположение включает mClassLoader в его mExtras, а в библиотеке Gson не удается создать ClassLoader с этой ошибкой:

RuntimeException: не удалось вызвать защищенный java.lang.ClassLoader () без аргументов

Кто-нибудь знает, почему ClassLoader включен в дополнительные параметры для моего местоположения и должен ли он заканчиваться в представлении JSON?

Я предполагаю, что могу исправить это, просто сохранив ключевые поля из объекта Location отдельно (например, долгота, широта, высота, время, точность), но было бы неплохо сохранить объект Location, если это возможно.

Я видел, что есть объект ExclusionStrategy, который я мог бы использовать для исключения полей, но я не был уверен, могу ли я / мог использовать это, чтобы исключить дополнительные функции из моего местоположения …

FYI, вот данные JSON для моего объекта Location (с изменением долготы и широты, чтобы скрыть меня):

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

Вот пример, который содержит mExtras, когда код не сбой:

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

Проблема в том, что вы пытаетесь просто преобразовать системный класс ( Location ) в JSON. И, как вы видите, у вас возникают проблемы с сериализацией внутренних состояний / конкретных Java-объектов. JSON понимается как полу-общий способ передачи информации.

Вы не @Expose легко использовать аннотацию @Expose потому что это не ваш класс; Что потребует изменения исходного кода для Location или путем довольно обширного процесса добавления их во время выполнения с использованием jassist (см .: http://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime -to.html )

Глядя на класс Location , я бы просто создал пользовательский Gial Serializer и Deserializer и покончил с этим. На самом деле вас интересуют данные GPS, а не внутренние элементы самого класса. Вы просто создаете JSON, содержащий необходимую информацию в сериализаторе, используя геттеры, а затем в Deserializer вы создаете новый экземпляр Location и заполняете его информацией из предоставленного JSON, используя публичные сеттеры.

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

Теперь в вашем коде вы используете GsonBuilder и регистрируете классы:

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

Это должно в значительной степени позаботиться об этом.

Подумайте о создании настраиваемого объекта, который моделирует ваш GSON, анализирует содержимое объекта на объект и поле в поле

что-то вроде

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

Таким образом, вы можете получить полный контроль над синтаксическим разбором и добавить блок try \ catch в критическую часть mExtra, вы можете легко исключить блок или управлять исключением по своему усмотрению.