android – Gson中的RuntimeException解析JSON:无法调用受保护的java.lang.ClassLoader()而没有args

我继承了一些代码,使用Gson将我们的应用程序状态保存为 JSON,然后使用 fromJson读取它.
Gson gson = createGson();
gson.fromJson(objString,myClass);

其中一个保存的字段是Location.不幸的是,很有可能解析保存的数据失败,因为我保存的Location在其mExtras中包含一个mClassLoader,而Gson库无法使用此错误创建ClassLoader:

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

有谁知道为什么ClassLoader被包含在我的Location的附加内容中,以及它是否应该以JSON表示结尾?

我假设我可以通过单独保存位置对象中的关键字段(例如经度,纬度,高度,时间,精度)来解决这个问题,但如果可能的话,保存位置对象会很好.

我看到有一个ExclusionStrategy对象可用于排除字段,但我不确定是否可以/应该使用它来排除我位置内的额外内容

仅供参考,这是我的Location对象的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
    },"mAllowFds": true
}

解决方法

问题是你试图直接将系统提供的类(Location)转换为JSON.而且,正如您所看到的,在序列化内部状态/ Java特定事物时会遇到问题. JSON是一种传递信息的半通用方式.

你不能轻易使用@Expose注释,因为它不是你的类;这将需要修改Location的源代码或通过使用jassist在运行时添加它们的相当广泛的过程(参见:http://ayoubelabbassi.blogspot.com/2011/01/how-to-add-annotations-at-runtime-to.html)

查看Location类,我只需创建一个自定义Gson Serializer和Deserializer并完成它.你真正感兴趣的是GPS数据,而不是类本身的内部.您只需使用getter构建包含序列化程序中所需信息的JSON,然后在Deserializer中创建一个新的Location实例,并使用公共setter从提供的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,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(); 
...

这应该照顾它.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...