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, вы можете исключить блок или легко управлять исключением.