简体   繁体   中英

nested generic parameter as a method parameter - Java

Based on this question How to get a class instance of generics type T I have implemented the following class:

public class OkJsonConverter<T> {

    final Class<T> typeParameterClass;

    public OkJsonConverter(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    protected T processJson(String json) throws OkClientException {
        T object = null;
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode jsonNode = objectMapper.readTree(json);

            if (jsonNode.get("error_code") != null) {
                Error error = objectMapper.treeToValue(jsonNode, Error.class);
                throw new OkClientException("API returned error", error);
            } else {
                object = objectMapper.treeToValue(jsonNode, typeParameterClass);
            }
        } catch (IOException e) {
            throw new OkClientException("unable to process json", e);
        }
        return object;
    }

}

I can use this class with a generic parameters, for example:

return new OkJsonConverter<User>(User.class).processJson(response.getBody());

but right now I'm struggling how to make it working with a nested generic parameter like this one List<Method>

This code doesn't work:

 return new OkJsonConverter<List<Method>>(List<Method>.class).processJson(response.getBody());

Please help to change this code in order to get it working.

Java doesn't have any way to represent that type as a Class . The closest approximation you can get is (Class<List<Method>>) (Class) List.class , but that cast just papers over that you're just looking at a basic List that doesn't know its element type.

Whether or not that works with your JSON converter isn't clear, but should be specified in the documentation of the converter you're using, which will have to deal with this itself, since this is a universal problem in Java when you're trying to reflect on generic types.

Finally, thanks to user3707125 I have found a way how to implement this:

Corrected by idierL

public class OkJsonConverter {

private static final String ERROR_CODE_FIELD_NAME = "error_code";

protected <T> T readTreeToValue(String json, TypeReference<T> valueTypeRef) throws OkClientException {
    T object = null;

    ObjectMapper objectMapper = new ObjectMapper();
    try {
        JsonNode jsonNode = objectMapper.readTree(json);

        if (jsonNode.has(ERROR_CODE_FIELD_NAME)) {
            Error error = objectMapper.treeToValue(jsonNode, Error.class);
            throw new OkClientException("Ok API returned error", error);
        } else {
            JavaType type = objectMapper.getTypeFactory().constructType(valueTypeRef);
            object = objectMapper.convertValue(jsonNode, type);
        }
    } catch (IOException e) {
        throw new OkClientException("Unable to process JSON", e);
    }

    return object;
}

}

Now, the following code works fine:

List<Method> result = new OkJsonConverter().readTreeToValue(response.getBody(), new TypeReference<List<Method>>() {});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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