JSON - 使用Gson反序列化客户端类

the*_*dor 3 java google-app-engine serialization gson google-cloud-endpoints

我在使用Google Gson反序列化类时遇到问题.这个问题困扰了我好几天,我找不到解决办法.

我创建了一个简单的测试用例,这是我班级的最小工作子集:

import java.util.Date;

import com.google.api.client.util.DateTime;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Test {
public static void main(String[] args) {

    GsonBuilder builder = new GsonBuilder();

    Gson gson = builder.create();

    DateTest dt = new DateTest(new Date());
    String j1 = gson.toJson(dt);
    System.out.println(j1);
    DateTest dt2 = gson.fromJson(j1, DateTest.class);
    System.out.println(dt2);

}

static class DateTest {
    @com.google.api.client.util.Key
    private final DateTime date;

    public DateTest(Date dt) {
        this.date = new DateTime(dt);
    }

    @Override
    public String toString() {
        return date.toString();
    }
}
}
Run Code Online (Sandbox Code Playgroud)

这产生了所需的输出.

序列化为:{"date":{"value":1381503448717,"dateOnly":false,"tzShift":60}}反序列化回:2013-10-11T15:57:28.717 + 01:00

但是,我尝试序列化的类是使用"生成云端点客户端库"从Google App Engine类自动生成的(这意味着我无法/不愿意修改它,但这个类可以通过jars对JSON进行序列化/反序列化)我有类路径 - 请参阅https://developers.google.com/appengine/docs/java/endpoints/consume_android).

经过大量测试后我发现问题是自动生成的类"扩展com.google.api.client.json.GenericJson" - 如果您将代码更改为:

static class DateTest extends com.google.api.client.json.GenericJson{
Run Code Online (Sandbox Code Playgroud)

序列化成功(具有相同的输出)但反序列化失败:

Exception in thread "main" java.lang.ClassCastException: Cannot cast java.util.LinkedHashMap to Test$DateTest
at java.lang.Class.cast(Unknown Source)
at com.google.gson.Gson.fromJson(Gson.java:643)
at Test.main(Test.java:17)
Run Code Online (Sandbox Code Playgroud)

Android似乎给出了更详细的输出,问题是任何非基本类属性都失败了.

我的问题是 - 如何修改反序列化代码以使反序列化成功?我究竟做错了什么?

由于我的项目能够从网络反序列化相同的JSON对象,请注意我不接受任何关于"尝试使用另一个JSON库"的答案.

the*_*dor 8

经过一段时间挖掘Google代码后,我发现以下代码解决了我的问题:

public static void main(String[] args) {

    GsonFactory factory= new GsonFactory();

    DateTest dt = new DateTest(new Date());
    String j1 = factory.toString(dt);
    System.out.println(j1);
    DateTest dt2 = factory.fromString(j1, DateTest.class);
    System.out.println(dt2);

}
Run Code Online (Sandbox Code Playgroud)

希望这将有助于未来的其他人.

  • 对于任何偶然发现这一点的人,让我来看看为什么会这样.原始代码使用`Gson`,而这个新代码使用`GsonFactory`.关键的区别在于Gson的包名是`com.google.gson.Gson`而GsonFactory是`com.google.api.client.json.gson.GsonFactory`.或者换句话说,它的包开始与Endpoints使用的`GenericJson`类相同.因此,Google必须在两个Gson类之间使用稍微不同的序列化规则.(在我的代码中,我注意到longs在Gson中直接保存为long,但是作为GsonFactory中的Strings保存.) (2认同)