3

我有一個使用Google Gson反序列化類的問題。這個問題困擾了我好幾天,我找不到解決方案。JSON - 使用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(); 
    } 
} 
} 

這將產生所需的輸出。

序列化到: { 「日期」:{ 「值」:1381503448717 「dateOnly」:假 「tzShift」:60}} 反序列化回: 2013-10-11T15:57:28.717 + 01 :00

但是,我嘗試序列化的類是使用「生成雲端點客戶端庫」從Google App Engine類自動生成的(意思是我不能/不願意修改它,但同時該類也是可序列化的/反序列化到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{ 

系列化成功(與相同輸出),但deserialising失敗:

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) 

的Android似乎給人一種更詳細的輸出,這個問題是任何非基本類屬性失敗。

我的問題是 - 如何修改我的反序列化代碼,使反序列化成功?我究竟做錯了什麼?

由於我的項目能夠從網絡反序列化相同的JSON對象,請注意,我不會接受任何類型的「嘗試使用其他JSON庫」的答案。

+0

請說明您實際嘗試序列化/反序列化的類。 –

+0

我想反序列化DateTest,擴展GenericJson的版本 – thedayofcondor

+0

你能給我們帶來一個你無法反序列化的JSON的例子嗎?我運行了你的測試用例,事實上,一切正常。所以這個問題必須在JSON中給你Google。 – 4gus71n

回答

8

通過谷歌代碼挖掘的一個週末後,我發現下面的代碼解決了我的問題:

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); 

} 

希望這將幫助其他人的未來。

+0

你從哪裏得到GsonFactory?什麼maven artefact版本的gson?嘗試了1.7.2,2.2,2.2.4,並沒有找到那個類 - 只有GsonBuilder沒有幫助。 – Vasile

+0

@Vasile - google-http-client-gson-x.xx.x.jar中的com.google.api.client.json.gson.GsonFactory(我相信它是在標準的AppEngine Android客戶端庫中) – thedayofcondor

+2

對於其他人誰絆倒了這一點,讓我擴大爲什麼這個作品。原始代碼使用'Gson',而這個新代碼使用'GsonFactory'。關鍵區別在於Gson的包名是'com.google.gson.Gson',而GsonFactory是'com.google.api。client.json.gson.GsonFactory'。或者換句話說,它的包開始與'GenericJson'類終結點使用相同。因此,Google必須在兩個Gson類之間使用稍微不同的序列化規則。 (在我的代碼中,我注意到多頭在Gson中被直接保存爲多頭,但是在GsonFactory中作爲字符串。) –