使用java泛型反序列化

时间:2018-04-20 10:04:38

标签: java class generics java-8

考虑这个外部执行类

public class ExternalCommands {

    private Logger log = LoggerFactory.getLogger(ExternalCommands.class);

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public <T> CustomResponse<T> executeQuery(Clients client, Query query, Class<T> classType) throws Exception {
        if (Objects.isNull(clients))
            throw new Exception("external client is null in external commands");

        log.debug("Query : {}", query);
        Response queryResponse = clients.getElasticClient().executeQuery(query);
        log.debug("query response : {}", queryResponse);
        if (queryResponse.status() == 200) {
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(CustomResponse.class, classType);  // This is the coding sin m talking about
            return objectMapper.readValue(queryResponse.body().asInputStream(), javaType);
        }
    }
}

所以基本上这个executeQuery函数从弹性客户端获取query的所有数据,并根据函数中发送的通用classType对其进行反序列化。 />  这更像是显式执行deserialisation而不是使用 Generics

见以下有关此执行如何与内联注释一起使用的代码:

public ArrayList<EmpData> getEmpData() throws Exception {
    ArrayList<EmpData> merchantUrnMap = new ArrayList<>();

    List<Filter> filters = new ArrayList<>();
    filters.add("Added filter 1 here");
    filters.add("Added filter 2 here");
    filters.add("Added filter 3 here");

    ExternalCommands commands = new ExternalCommands();
    Query query = commands.getQuery(filters);
    // get "clients"

    // this is how it works now
    CustomResponse<EmpData> response = commands.executeQuery(clients, query, EmpData.class);

    // this is how i WANT IT TO WORK - without passing "EmpData.class"
    // but in this case <T> in "CustomResponse<T>" would not deserialise to "EmpData"
    // resulting in LinkedHashMap in deseralised object instead of class object
    // CustomResponse<EmpData> response = commands.<EmpData>executeQuery(clients, query); 


    // some operations
    return response

}

有关如何实现这一目标的任何建议?

1 个答案:

答案 0 :(得分:2)

案例1:假设constructParametricType要求classType参数正常运行,并且您无法更改隐含但未在发布的代码中提供的方法/类的实现。

由于Java中的type erasure,您提出的方法签名/调用无法实现。

您在classType来电中使用了constructParametricType(CustomResponse.class, classType),并且您试图以某种方式将classType替换为T。这是不可能的,因为编译代码时,T将被完全删除。由于constructParametricType(CustomResponse.class, T.class)在运行时不存在,因此无法执行T之类的操作。

正确的解决方案是将类作为方法参数传递,这正是您现有方法所做的。

案例2:您确实希望接听电话commands.<EmpData>executeQuery(clients, query);,并且您愿意更改任何内容以实现该目标。

由于我们无法将T作为参数传递给constructParametricType,因此必须将其称为constructParametricType(CustomResponse.class),但需要返回代表JavaType的{​​{1}} 。唯一的方法是声明

CustomResponse<T>

请注意,<T> JavaType<T> constructParametricType(Class<?> cls) 现在也必须出于同样的原因进行参数化(我们无法在运行时获得JavaType)。最后,我们必须声明

T

匹配声明的返回类型CustomResponse<T> readValue(InputStream stream, JavaType<T> javaType)

完成所有这些更改后,该行

executeQuery

应该编译。这是一个最小的例子:

CustomResponse<EmpData> response = commands.<EmpData>executeQuery(clients, query);

请注意,在系统的其余部分(特别是参数化class CustomResponse<T> {} class Clients{} class Query{} class EmpData{} class ObjectMapper { JavaTypeFactory getTypeFactory() { return new JavaTypeFactory(); } <T> CustomResponse<T> readValue(InputStream s, JavaType<T> j) { return new CustomResponse<>(); } } class JavaTypeFactory { <T> JavaType<T> constructParametricType(Class<?> cls) { return new JavaType<>(cls); } } class JavaType<T> { JavaType(Class<?> cls) {} } class ExternalCommands { private static final ObjectMapper objectMapper = new ObjectMapper(); public <T> CustomResponse<T> executeQuery(Clients clients, Query query) throws Exception { InputStream queryResponseStream = null; JavaType<T> javaType = objectMapper.getTypeFactory().<T>constructParametricType(CustomResponse.class); return objectMapper.readValue(queryResponseStream, javaType); } } class SomeClass { public void getEmpData() throws Exception { ExternalCommands commands = new ExternalCommands(); Query query = null; Clients clients = null; CustomResponse<EmpData> response = commands.<EmpData>executeQuery(clients, query); } } )中,某些所描述的更改可能并不容易/可能,并且我不推荐这种方法。我建议坚持你拥有的东西;这是IMO最干净的方法。

相关问题