【问题标题】:generic parser return hash-map and not Pojo通用解析器返回哈希映射而不是 Pojo
【发布时间】:2016-03-29 12:32:41
【问题描述】:

我有这个代码(A):

JsonFileHandler<Device> jsonFileHandlerDevice;
final List<Device> devicesList = jsonFileHandlerDevice.getList();

class JsonFileHandler<T>:

@Override
public List<T> getList() {
    List<T> t = null;
    ObjectMapper mapper = new ObjectMapper();

    if (!file.exists()) {
        return null;
    } else {
        try {
            t = mapper.readValue(file, new TypeReference<List<T>>(){});
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    return t;
}

这个代码(B):

@Override
public List<Device> getList() {
    List<Device> t = null;
    ObjectMapper mapper = new ObjectMapper();

    if (!file.exists()) {
        return null;
    } else {
        try {
            t = mapper.readValue(file, new TypeReference<List<Device>>(){});
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    return t;
}

还有这个 json 文件:

[ {
  "mobileOs" : "ios",
  "osVersion" : 4.2,
  "allocatedPort" : 0,
  "hasSim" : false,
  "uuid" : "uuid2",
  "wazers" : [ {
    "email" : null,
    "emailPassword" : null,
    "first" : null,
    "last" : null,
    "driverPhone" : null,
    "riderPhone" : null,
    "username" : null,
    "password" : null,
    "workEmail" : null,
    "car" : null,
    "model" : null,
    "color" : null,
    "plate" : null,
    "obId" : null
  } ],
  "riders" : [ {
    "email" : null,
    "emailPassword" : null,
    "first" : null,
    "last" : null,
    "driverPhone" : null,
    "riderPhone" : null,
    "username" : null,
    "password" : null,
    "workEmail" : null,
    "car" : null,
    "model" : null,
    "color" : null,
    "plate" : null,
    "obId" : null
  }, {
    "email" : null,
    "emailPassword" : null,
    "first" : null,
    "last" : null,
    "driverPhone" : null,
    "riderPhone" : null,
    "username" : null,
    "password" : null,
    "workEmail" : null,
    "car" : null,
    "model" : null,
    "color" : null,
    "plate" : null,
    "obId" : null
  } ]
} ]

代码仅在执行代码时解析OK(B)

当运行代码 (A) 时,我们得到一个哈希映射而不是 Pojo Device

【问题讨论】:

    标签: java json parsing


    【解决方案1】:

    我假设您可以通过 Spring 或任何您用作 IoC 容器的方式获取类的泛型类型,因此为简单起见,我通过构造函数传递类型。话虽如此,我目前可以为您的问题想到的一种解决方案如下:

    class JsonFileHandler<T> {
    
        private File file = new File("/Users/dambros/Desktop/test");
        private final Class<T> type;
    
        public JsonFileHandler(Class<T> type) {
            this.type = type;
        }
    
        public List<T> getList() {
            List<T> t;
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
            if (!file.exists()) {
                return null;
            } else {
                try {
                    JavaType javaType = mapper.getTypeFactory().constructParametrizedType(ArrayList.class, List.class, type);
                    t = mapper.readValue(file, javaType);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
            return t;
        }
    
    }
    

    使用如下调用将返回您的 POJO 列表而不是 HashMap:

    JsonFileHandler<Device> jsonFileHandlerDevice = new JsonFileHandler<>(Device.class);
    final List<Device> devicesList = jsonFileHandlerDevice.getList();
    

    Obs.:映射器配置只是为了避免将所有条目写入 JSON 并简化测试。

    【讨论】:

    • 为什么我的代码适用于new TypeReference&lt;List&lt;Device&gt;&gt;() 而不适用于new TypeReference&lt;List&lt;T&gt;&gt;()
    • 问题出在类型擦除上。由于 T 只是一个类型变量,所以就像说T extends Object。因此,除非您指明实际的类类型,否则 Jackson 会将 JSONObject 绑定为 Map。在您的示例中,当您说 new TypeReference&lt;List&lt;Device&gt;&gt;() 时,这正是您正在做的事情。
    • 如何将new TypeReference&lt;List&lt;Device&gt;&gt;() 替换为通用泛型?
    • 你不能像使用 TypeReference 那样使用它,我已经在上面向你展示了它应该如何使用。唯一对您来说应该不同的是,由于您使用的是依赖注入,因此您如何获得泛型类型。
    猜你喜欢
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多