3

我成功地使用 Gson 将 json 放入对象中。它在具有 android 2.2(模拟器和真实设备)的设备上就像一个魅力,当我部署到 android 4.0 及更高版本(模拟器和设备)时,我得到了这个非常奇怪的异常。

我已经确认 json 字符串没有问题,因为相同的代码在旧设备上运行良好。

这里肯定会抛出异常:

Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); return gson.fromJson(jsonString, t);

在 fromJson 方法中。

有任何想法吗?

Json String:(必须从 json 中的 url 中删除 http://)

{“session_id”:“a89d8cd07e356”,
    “shoutout_items”:[{“attachment_url”:“xxxxxx.mobi/pic.php?id=478ba67a44d”,
        "attachment_url_full_size" : "xxxxxx.mobi/pic.php?id=01810a5e9f6e7065cd4",
        “expires_at”:1363264081,
        “have_attachment”:是的,
        "message_text" : "嗨",
        “合作伙伴”:{“国家代码”:“za”,
            “性别”:“男性”,
            “昵称”:“昵称”,
            "profile_pic_full_size_url" : "xxxxxx.mobi/pic.php?id=810a5e9f6e7065cd43629f1",
            "profile_pic_url" : "xxxxxx.mobi/pic.php?id=23ca67a44d23",
            “profile_summary”:“20,DBN”
          },
        “shoutout_id”:31170,
        “类型”:“大喊”
      },
      {“附件网址”:空,
        “attachment_url_full_size”:空,
        “expires_at”:1363264081,
        “有附件”:假,
        "message_text" : "你好",
        “合作伙伴”:{“国家代码”:“za”,
            “性别”:“男性”,
            “昵称”:“标记”,
            "profile_pic_full_size_url" : "xxxxxx.mobi/pic.php?id=2db9e7f86b9bf7ca",
            "profile_pic_url" : "xxxxxx.mobi/pic.php?id=b110191f1afac",
            “profile_summary”:“40,DBN”
          },
        “shoutout_id”:31322,
        “类型”:“大喊”
      }
    ]
}

堆栈跟踪:

 03-14 14:56:02.200: E/AndroidRuntime(19588): FATAL EXCEPTION: main
    03-14 14:56:02.200: E/AndroidRuntime(19588): java.lang.RuntimeException: Unable to start activity ComponentInfo{mobi.smiggle.android/mobi.smiggle.android.MainFragmentActivity}: java.lang.IllegalArgumentException: class android.text.BoringLayout declares multiple JSON fields named m_paint
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1968)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1993)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.app.ActivityThread.access$600(ActivityThread.java:127)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1159)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.os.Handler.dispatchMessage(Handler.java:99)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.os.Looper.loop(Looper.java:137)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at android.app.ActivityThread.main(ActivityThread.java:4507)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at java.lang.reflect.Method.invokeNative(Native Method)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at java.lang.reflect.Method.invoke(Method.java:511)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at dalvik.system.NativeStart.main(Native Method)
    03-14 14:56:02.200: E/AndroidRuntime(19588): Caused by: java.lang.IllegalArgumentException: class android.text.BoringLayout declares multiple JSON fields named m_paint
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:122)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.Gson.getAdapter(Gson.java:353)
    03-14 14:56:02.200: E/AndroidRuntime(19588):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:
4

1 回答 1

2

我发现,如果您的实例t从任何android视图组件(例如 Button)扩展或具有从任何android视图组件扩展的类字段,您将得到这样的异常

出于某种原因,这个库不能再序列化视图组件了。因此,您可以添加排除策略。例如,此策略将排除所有字段,但带有注解@SerializedName 的字段除外:

class Exclude implements ExclusionStrategy {

@Override
public boolean shouldSkipClass(Class<?> arg0) {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean shouldSkipField(FieldAttributes field) {
    SerializedName sn = field.getAnnotation(SerializedName.class);
    if(sn != null)
        return false;
    return true;
}}

假设我们有示例 Json:

private final String jsonSample= "{ \"Sample\": { \"field1\":1, \"field2\":2}}";

这是示例代码:

 private void parseJson(){
    Exclude ex = new Exclude();
    Gson gson = new GsonBuilder().create();

    GsonObject gObject = gson.fromJson(jsonSample, GsonObject.class);

}

class GsonObject{
    @SerializedName("Sample")
    public Smpl smpl;

//  private Button btn;  <-- Uncomment this line, and you will get your error!

    class Smpl{
        @SerializedName("field1")
        int fl1;
        @SerializedName("field2")
        int fl2;
    }
}

但是在添加了我上面写的排除策略之后:

    Exclude ex = new Exclude();
    Gson gson = new GsonBuilder().addDeserializationExclusionStrategy(ex).addSerializationExclusionStrategy(ex).create();

一切正常。

最后我们有以下测试应用程序:

public class MainActivity extends Activity {

private final String jsonSample= "{ \"Sample\": { \"field1\":1, \"field2\":2}}";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    parseJson();
}

private void parseJson(){
    Exclude ex = new Exclude();
//  Gson gson = new GsonBuilder().create(); <-- without EX strategy it will try to serrialaze Button field in our GsonObject, and throws an exeption
    Gson gson = new GsonBuilder().addDeserializationExclusionStrategy(ex).addSerializationExclusionStrategy(ex).create();

    GsonObject gObject = gson.fromJson(jsonSample, GsonObject.class);

    Toast.makeText(this, "Gson" + gObject.smpl.fl1 + " " + gObject.smpl.fl2, Toast.LENGTH_LONG).show();

}

class GsonObject{
    @SerializedName("Sample")
    public Smpl smpl;

    private Button btn; // <-- this field is our reason of this strange exception on Gson serialization

    class Smpl{
        @SerializedName("field1")
        int fl1;
        @SerializedName("field2")
        int fl2;
    }
}
}

class Exclude implements ExclusionStrategy {

    @Override
    public boolean shouldSkipClass(Class<?> arg0) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean shouldSkipField(FieldAttributes field) {
        SerializedName ns = field.getAnnotation(SerializedName.class);
        if(ns != null)
            return false;
        return true;
    }

}

ps对不起我的英语)

于 2013-04-04T18:05:03.990 回答