2011-09-04 28 views
6

Tôi có một lớp chung chứa một trường kiểu T, Gson tuần tự hóa trường này làm đối tượng trống. Tôi đã bao gồm mã dưới đây để chứng minh vấn đề. Đọc lại JSON có vẻ tốt (miễn là bạn cung cấp đúng loại mã thông báo).Tại sao Gson.toJson tuần tự hóa một trường chung thành một đối tượng JSON trống?

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 
    } 
} 

Trả lời

8

Từ tài liệu của họ:

Khi bạn gọi toJson (obj), Gson gọi obj.getClass() để có được thông tin về các lĩnh vực để serialize. Tương tự, bạn thường có thể vượt qua đối tượng MyClass.class trong phương thức fromJson (json, MyClass.class). Điều này làm việc tốt nếu đối tượng là một loại không chung chung. Tuy nhiên, nếu đối tượng thuộc loại chung thì thông tin loại Chung sẽ bị mất do Loại Java Xóa

Bạn có thể giải quyết vấn đề này bằng cách chỉ định loại tham số chính xác cho loại chung của mình. Bạn có thể làm điều này bằng cách sử dụng lớp TypeToken.

Họ đưa ra ví dụ sau đây cho một List<T>:

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

Vì vậy, đối mã của bạn, bạn cần phải ...

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

Cảm ơn - điều này làm việc , nhưng có vẻ mâu thuẫn với phần này: https://sites.google.com/site/gson/gson-user-guide#TOC-Collections-Ví dụ nơi một 'Bộ sưu tập 'được tuần tự hóa mà không có mã thông báo loại. Bạn có thể giải thích sự khác biệt giữa ví dụ của tôi và ví dụ về hướng dẫn sử dụng không? – zorgbargle

+0

Tôi sẽ nghi ngờ họ có mã để đối phó với Bộ sưu tập và Mảng cụ thể, nhưng bên ngoài đó ... không có ý tưởng. –

+0

Dường như đây là trường hợp. Java Generics như thường lệ lãng phí nhiều thời gian của tôi hơn nếu tôi chỉ là đối phó với các đối tượng thô. Cảm ơn đã giúp đỡ. – zorgbargle

Các vấn đề liên quan