2013-08-27 55 views
0

我試圖將從服務器獲取的JSON反序列化爲其原始POJO表單。我知道原始對象(我有服務器代碼的來源),但似乎我錯過了一些東西。Gson無法反序列化List <Serializable>

這裏是最小的代碼示例我可以組裝,說明我的問題:

package mycompany.mypackage; 
import java.io.Serializable; 
import java.lang.reflect.Type; 
import java.util.ArrayList; 
import java.util.List; 
import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.InstanceCreator; 

public class GsonSerializeTest { 

    /* main method to illustrate the problem */ 
    public static void main(String[] args) { 
     Serializable[] identifiers= {"ITEM",12345678,"abc.def.ghijkl.mnopqr",87654321}; 
     EntityUid uid = new GsonSerializeTest().new EntityUid(identifiers); 
     Gson converter = new GsonBuilder().registerTypeAdapter(Serializable.class, new GsonSerializeTest().new SerializableInstanceCreator()).create(); 
     String json = converter.toJson(uid); 
     System.out.println("Converted to string: " + json); 
     EntityUid uid2 = converter.fromJson(json, EntityUid.class); // ERROR 
     System.out.println("Converted back to object: " + uid2); 
    } 

    /* the POJO that gets serialized and fails while deserializing */ 
    public class EntityUid implements Serializable { 
     private final List<Serializable> identifier = new ArrayList<Serializable>(); 

     public EntityUid(final Serializable... identifier) { 
      for (Serializable partialIdentifier : identifier) { 
       this.identifier.add(partialIdentifier); 
      } 
     } 
    } 

    /* Class for generating Serializable instances */ 
    public class SerializableInstanceCreator implements InstanceCreator<Serializable> { 
     public Serializable createInstance(Type arg0) { 
      return new String(); 
     } 
    } 
} 

這準備EntityUid對象,將其序列(就像服務器一樣)變成這樣:

Converted to string: {"identifier":["ITEM",12345678,"abc.def.ghijkl.mnopqr",87654321]} 

然後嘗試將其反序列化爲原始對象,但是會失敗,如下所示:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 17 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176) 
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172) 
    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) 
    at mycompany.mypackage.GsonSerializeTest.main(GsonSerializeTest.java:19) 
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 17 
    at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:374) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165) 
    ... 10 more 

請問有人請給我一個指示,指出我可能錯過了什麼?提前感謝!

回答

2

請閱讀Serializing and Deserializing Collection with Objects of Arbitrary Types

下面的代碼可以工作。

import java.util.ArrayList; 
import java.util.List; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 

public class GsonSerializeTest { 

    /* main method to illustrate the problem */ 
    public static void main(String[] args) { 
     Object[] identifiers= {12345678,"ITEM","abc.def.ghijkl.mnopqr",87654321}; 
     EntityUid uid = new EntityUid(identifiers); 
     Gson converter = new GsonBuilder().create(); 
     String json = converter.toJson(uid); 
     System.out.println("Converted to string: " + json); 
     EntityUid uid2 = converter.fromJson(json, EntityUid.class); // ERROR 
     System.out.println("Converted back to object: " + uid2); 
    } 

    /* the POJO that gets serialized and fails while deserializing */ 
    public static class EntityUid { 
     private final List<Object> identifier = new ArrayList<Object>(); 

     public EntityUid(final Object... identifier) { 
      for (Object partialIdentifier : identifier) { 
       this.identifier.add(partialIdentifier); 
      } 
     } 

     @Override 
     public String toString() { 
      return "EntityUid [identifier=" + identifier + "]"; 
     } 


    } 
} 
+0

謝謝你的回答。如果我看得很清楚,建議我將EntityUid的標識符字段更改爲列表。這確實可以解決問題,但我無法控制服務器的代碼,我只能查看它並使用它。但是,我會嘗試以這種方式定義一個EntityUid對象,並查看它是否按預期工作。 – zovits

+0

我設法創建了一個基於原始類的新類,但是我的對象列表(受您的答案啓發)而不是可串行化列表。這個結構可以被用作給定JSON的反序列化模板。再次感謝你! – zovits

0

通過下面的帖子它會幫助你。

Android JSon error "Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2"

類別限制:

可以序列化的任意對象的集合,但不能從它反序列化因爲有沒有辦法用戶指示生成的對象反序列化的類型,集合必須是特定的泛型類型所有這些都是有意義的,並且在遵循良好的Java編碼實踐時很少成爲問題

+0

感謝您的回答,但我認爲List 確實是一個特定的類型。在鏈接問題中,JSON是一個數組,並且該海報試圖將其反序列化爲一個對象,但由於明確的原因而失敗。以前我試圖將這個例子反序列化成List :'String input =「[\」ITEM \「,12345678,\」abc.def.ghijkl.mnopqr \「,87654321]」;'並且它的工作完美因此我認爲這個系列是正確的) – zovits