【问题标题】:JSON to Java object in Android not working with GSONAndroid 中的 JSON 到 Java 对象不能与 GSON 一起使用
【发布时间】:2014-02-23 14:54:22
【问题描述】:

我正在尝试将一些 JSON 转换为 android 中的 java 对象,但它似乎不起作用。

Gson gson = new Gson();
Person person = gson.fromJson(s, Person.class);
Toast toast = Toast.makeText(getApplicationContext(), "Welcome back " + person.getDisplayName(), duration);
toast.show();

Person.class 在哪里

com.google.api.services.plus.model.Person

我收到类型转换错误,例如:

wrong object type: Ljava/lang/Double; Ljava/lang/Integer;
java.lang.IllegalArgumentException: invalid value for field

但我想重用 API 库中的这个模型对象,有没有办法解决这个问题?

编辑:

为了以更简单的形式证明这个问题,请参考这个例子。

com.google.api.services.plus.model.Person;

Gson g = new Gson();

    Person p1 = new Person();
    p1.setDisplayName("Test");
    p1.setCircledByCount(10);

    String json = g.toJson(p1);
    Person fromJson = g.fromJson(json, Person.class);
    System.out.println(fromJson.getDisplayName());

抛出同样的异常。

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)

我做错了吗? 谢谢

【问题讨论】:

  • 发布你的模型类和json
  • 老实说,您不应该在该类中使用 GSON。它不是为与 GSON 一起使用而设计的。它有自己的内置逻辑,用于将自身序列化为 JSON,并且它所属的库处理对它的反序列化。

标签: java android json google-api gson


【解决方案1】:

问题是您使用的类并非旨在/旨在与 Gson 一起使用。

核心问题是Person 扩展GenericJson 扩展GenericData 扩展AbstractMap<String, Object> ... 是问题。

当 Gson 尝试反序列化 JSON 时,它使用了它的 MapTypeAdapterFactory,不幸的是,这会导致 "circledByCount" 的 JSON 数字类型在 Java 中被读取为 Double

然后这个Person 类的复杂性开始发挥作用。如果您查看源代码,它实际上使用注释并覆盖put 方法来填充Person 中的字段。如果您查看堆栈跟踪,您实际上可以看到发生了什么:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:680)
    at com.google.api.client.util.FieldInfo.setFieldValue(FieldInfo.java:245)
    at com.google.api.client.util.FieldInfo.setValue(FieldInfo.java:206)
    at com.google.api.client.util.GenericData.put(GenericData.java:103)
    at com.google.api.client.util.GenericData.put(GenericData.java:47)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at com.google.gson.Gson.fromJson(Gson.java:689)

Gson 正在调用GenericDataput() 方法(因为它知道这是一个Map)。该方法实际上通过反射填充了带注释的circledByCount 字段。而且……这是错误的类型。

所以,基本上......这不适用于 Gson。至少在不编写自定义 JsonDeserializer 的情况下并非如此,但是查看类,这将是相当复杂的。

【讨论】:

  • 感谢您的详细解释。在客户端库的许多其他地方使用模型类并使用与 GSON 不同的 json 序列化程序似乎很奇怪。不过,我确信这是有正当理由的!
【解决方案2】:

您的人员类必须具有与您解析的 JSON 完全相同的文件和名称。

【讨论】:

    【解决方案3】:

    您的 JSON String 具有 Double 值,并且您关心的 Person 对象具有 Integer 值。

    请检查两边的Person 对象。如果您在 Android 应用程序端复制并粘贴相同的 Person 对象会更好..

    【讨论】:

    • 它们与帖子中列出的 Google api 中的模型类相同。 json 由 spring mvc 控制器生成,该控制器返回一个 person 对象。服务器端 Jackson 序列化程序是否会导致问题?
    • 如果从服务器返回的 JSON 字符串没有问题,则不能是 Jackson 序列化程序的问题。仔细检查您的人员类..如果您可以在服务器和客户端双方提供 JSON 字符串和人员类..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    相关资源
    最近更新 更多