格森(Gson)对清单和班级进行了取消武装,擦除在这里是如何工作的? [英] Gson desearilize list and class, how does erasure work here?

查看:67
本文介绍了格森(Gson)对清单和班级进行了取消武装,擦除在这里是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算编写一个通用方法将json列表转换为带有类的特定列表.这是通用的json解析器:

I intend to write a generic method to convert a json list into it's specific list with class. This is the generic json parser:

public class JsonParserUtils {

    private static Gson gson = new Gson();

    public static <T> String toJson(T object) {
        if (object == null) {
            return null;
        }
        return gson.toJson(object);
    }

    public static <T> T fromJson(String json, Class<T> className) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        T object = gson.fromJson(json, className);
        return object;
    }

    public static <T> List<T> fromJsonList(String jsonList, Class<T> className) {
        // return gson.fromJson(jsonList, TypeToken.getParameterized(List.class, className).getType());
        return gson.fromJson(jsonList, new TypeToken<List<T>>() {}.getType());
    }

}

这是我要转换为Json并返回Pojo的虚拟类.

Here is a dummy class I'd like to convert to Json and back to Pojo.

public class City {

    private String city;

    public City(String city) {
        this.city = city;
    }

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

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

}

这是一个简单的测试,看是否有效:

Here is a simple test to see if it works:

public class TestParser {

    public static void main(String[] args) {
        City city = new City("test");
        String cityJson = JsonParserUtils.toJson(city);
        System.out.println(cityJson);

        City fromJson = JsonParserUtils.fromJson(cityJson, City.class);
        System.out.println(fromJson.getCity());  // Why does this work?

        List<City> list = new LinkedList<>();
        list.add(city);
        String cityListJson = JsonParserUtils.toJson(list);
        System.out.println(cityListJson);

        List<City> fromJsonList = JsonParserUtils.fromJsonList(cityListJson, City.class);
        System.out.println(fromJsonList.get(0).getCity()); // Why does this not work?


    }

}

控制台输出如下:

{"city":"test"}
test
[{"city":"test"}]
Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.jtraq.hospital.vos.City
    at com.jtraq.hospital.vos.TestParser.main(TestParser.java:24)

我正在努力理解为什么 fromJson(json,class)起作用,但是 fromJsonList(json,class)无效.如果应用擦除,那么它不适用于两种情况吗?为什么第一种方法弄清楚该类是 City 类型,而不是第二种情况下的 LinkedHashMap 类型?

I'm struggling to understand why fromJson(json, class) works but fromJsonList(json, class) doesn't. If erasure applies, then doesn't it apply to both cases? Why is it that first method figures out the class is of type City and not LinkedHashMap like in the second case?

推荐答案

类型擦除意味着 T 在运行时丢失,因此

Type erasure means that T is lost at runtime, so

new TypeToken<List<T>>() {}.getType()

成为

new TypeToken<List>() {}.getType()

这意味着Gson不知道列表元素的类型(城市).

which means that Gson doesn't know the list element type (City).

由于不知道将列表中的JSON对象解析为 City 对象,因此将其解析为 Map< String,Object> 对象,因此出现错误提示"地图无法投射到城市"的消息.

Since it doesn't know to parse the JSON objects in the list into City objects, it parses them into Map<String, Object> objects, hence the error message saying "Map cannot be cast to City".

使用 TypeToken.getParameterized()的注释代码将起作用,因此请坚持使用.

The commented code using TypeToken.getParameterized() will work, so just stick with that.

这篇关于格森(Gson)对清单和班级进行了取消武装,擦除在这里是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆