简体   繁体   English

为什么Gson.toJson将通用字段序列化为空的JSON对象?

[英]Why does Gson.toJson serialize a generic field to an empty JSON object?

I have a generic class containing a field of type T, Gson serializes this field as an empty object. 我有一个包含T类型字段的泛型类,Gson将此字段序列化为一个空对象。 I have included code below to demonstrate the issue. 我在下面提供了代码来演示这个问题。 Reading the JSON back seems fine (as long as you supply the correct type token). 阅读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
    }
}

From their docs: 从他们的文档:

When you call toJson(obj), Gson calls obj.getClass() to get information on the fields to serialize. 当你调用toJson(obj)时,Gson调用obj.getClass()来获取有关要序列化的字段的信息。 Similarly, you can typically pass MyClass.class object in the fromJson(json, MyClass.class) method. 类似地,您通常可以在fromJson(json,MyClass.class)方法中传递MyClass.class对象。 This works fine if the object is a non-generic type. 如果对象是非泛型类型,则此方法正常。 However, if the object is of a generic type, then the Generic type information is lost because of Java Type Erasure 但是,如果对象是泛型类型,则由于Java类型擦除而丢失通用类型信息

You can solve this problem by specifying the correct parameterized type for your generic type. 您可以通过为泛型类型指定正确的参数化类型来解决此问题。 You can do this by using the TypeToken class. 您可以使用TypeToken类来完成此操作。

They give the following example for a List<T> : 他们为List<T>提供以下示例:

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

So for your code, you'd need ... 所以对于你的代码,你需要......

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 https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM