繁体   English   中英

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

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

我有一个包含T类型字段的泛型类,Gson将此字段序列化为一个空对象。 我在下面提供了代码来演示这个问题。 阅读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
    }
}

从他们的文档:

当你调用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

暂无
暂无

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

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