2011-09-04 3 views
6

タイプTのフィールドを含むジェネリッククラスがあり、このフィールドは空のオブジェクトとしてシリアル化されます。私はこの問題を示すために以下のコードを含んでいます。 JSONを読み返すことは、(あなたが正しい型トークンを提供している限り)うまくいくように見えます。そのドキュメントからGson.toJsonは汎用フィールドを空のJSONオブジェクトにシリアル化するのはなぜですか?

import java.lang.reflect.Type; 
import com.google.gson.Gson; 
import com.google.gson.reflect.TypeToken; 

public class GsonIssue { 
    static class AbstractThing { 
     private String fieldA = "valueA"; 

     public String getFieldA() { 
      return fieldA; 
     } 

     public void setFieldA(String fieldA) { 
      this.fieldA = fieldA; 
     } 

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

    static class Thing extends AbstractThing { 
     private String fieldB = "valueB"; 

     @Override 
     public String toString() { 
      return "Thing [fieldB=" + fieldB + ", fieldA=" + getFieldA() + "]"; 
     } 
    } 

    static class Wrapper<T extends AbstractThing> { 
     private T abstractThing; 
     private String standardField = "standard value"; 

     public Wrapper(T abstractThing) { 
      this.abstractThing = abstractThing; 
     } 

     @Override 
     public String toString() { 
      return "Wrapper [abstractThing=" + abstractThing + ", standardField=" + standardField + "]"; 
     } 
    } 

    public static void main(String[] args) { 
     Wrapper<Thing> wrapper = new Wrapper<Thing>(new Thing()); 

     Gson gson = new Gson(); 
     String json = gson.toJson(wrapper); 
     System.out.println(json); 
     // prints : {"abstractThing":{},"standardField":"standard value"} 
     // so standardField is correctly serialized but not abstractThing. 

     // but if we manually construct the expected json string, and parse it back, we get the expected object structure 
     json = "{\"standardField\": \"some text\", " + 
       "\"abstractThing\":{\"fieldB\" : \"arb value\", \"fieldA\" : \"another arb value\"}}"; 

     Type type = new TypeToken<Wrapper<Thing>>() {}.getType(); 
     Object fromJson = gson.fromJson(json, type); 
     System.out.println(fromJson); 
     // prints : Wrapper [abstractThing=Thing [fieldB=arb value, fieldA=another arb value], standardField=some text] 
     // which is as expected 
    } 
} 

答えて

8

:あなたはtoJson(OBJ)を呼び出すと

、Gsonをシリアライズするためのフィールドに関する情報を取得するために)(obj.getClassを呼び出します。同様に、通常、fromJson(json、MyClass.class)メソッドでMyClass.classオブジェクトを渡すことができます。これは、オブジェクトが非ジェネリック型であれば問題ありません。オブジェクトがジェネリック型である場合には、その後、一般的なタイプの情報は、あなたがあなたのジェネリック型の正しいパラメータ化された型を指定することで、この問題を解決することができるためのJava型消去

で失われます。これを行うには、TypeTokenクラスを使用します。

彼らはList<T>ために、次の例を与える:

Type listType = new TypeToken<List<String>>() {}.getType(); 
gson.toJson(myStrings, listType); 

だからあなたのコードのために、あなたは...

Type myType = new TypeToken<Wrapper<Thing>>() {}.getType(); 
String json = gson.toJson(wrapper, myType); 

https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener

+0

を必要とするだろうおかげで - これは、作業を行いますこのセクションと矛盾しているようです:https://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Examplesここで 'Collection 'は型トークンなしで直列化されます。私の例とマニュアルの例の違いを説明できますか? – zorgbargle

+0

コレクションと配列を具体的に扱うコードがあると思われますが、それ以外のものはありません。 –

+0

このように見えます。 Javaのジェネリックスはいつものように私の時間の多くを無駄にしています。助けてくれてありがとう。 – zorgbargle

関連する問題