RuntimeException в Gson разборе JSON: не удалось вызвать защищенную java.ленг.ClassLoader() без аргументов
я унаследовал некоторый код, который сохраняет наше состояние приложения как JSON с помощью Gson, а затем читает его с помощью fromJson.
Gson gson = createGson();
gson.fromJson(objString, myClass);
одним из сохраняемых полей является расположение. К сожалению, очень редко синтаксический анализ этих сохраненных данных терпит неудачу, потому что мое сохраненное местоположение включает mClassLoader в его mExtras, и библиотека Gson не может создать загрузчик классов с этой ошибкой:
RuntimeException: не удалось вызовите защищенную java.ленг.ClassLoader () без args
кто-нибудь знает, почему загрузчик классов включается в дополнительные функции для моего местоположения и должен ли он заканчиваться в представлении JSON?
Я предполагаю, что могу исправить это, просто сохранив ключевые поля из объекта местоположения индивидуально (например, долгота, широта, высота, время, точность), но было бы неплохо сохранить объект местоположения, если это возможно.
Я видел, что есть ExclusionStrategy объект, который я мог бы использовать для исключения полей, но я не был уверен, что могу/должен использовать это, чтобы исключить экстры из моего местоположения...
FYI, вот данные JSON для моего объекта местоположения (с измененной долготой и широтой, чтобы скрыть меня):
{
<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
}
2 ответов
проблема в том, что вы пытаетесь просто прямо преобразовать системный класс (Location
) в JSON. И, как вы видите, вы сталкиваетесь с проблемами с сериализацией внутренних состояний / конкретных вещей Java. JSON подразумевается как полу-общий способ передачи информации.
вы не можете использовать @Expose
аннотация легко, потому что это не твой класс, который потребует изменения исходного кода Location
или через довольно обширный процесс добавления их во время выполнения с помощью jassist (см.: http://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime-to.html)
смотреть на!--2--> класс, я бы просто создал пользовательский сериализатор и десериализатор Gson и закончил с ним. На самом деле вас интересуют данные GPS, а не внутренние данные самого класса. Вы просто создаете JSON, содержащий необходимую информацию в сериализаторе, используя геттеры, а затем в Десериализаторе вы создаете новый пример 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, вы можете исключить блок или легко управлять исключением.