简体   繁体   中英

Java Generic Map not converted to proper type in runtime for Json converstion

I have one method which works fine when i use actual class, but don't give expected output when using generics.

Below is the method which works fine when using ABC class

public static List<ABC> getMemberViewRepresentation(Response response) throws JSONException, IOException {
        JSONObject jsonObj = new JSONObject(response.readEntity(String.class));
        ObjectMapper mapper = new ObjectMapper();
        JSONObject memberViewObj = (JSONObject)jsonObj.get("members");
        TypeReference<HashMap<String, ABC>> typeRef = new TypeReference<HashMap<String, ABC>>() {};        
        Map<String, ABC> map = mapper.readValue(memberViewObj.toString(), typeRef);
        return new ArrayList<>(map.values());
    }

This methods gives proper output which has list of type ABC.

But i want to write code such that i pass class dynamically so that this method can be used by anyone. So i have written below code, also i tried other way but none of them seems to work.

public static<T> List<T> getMemberViewRepresentation(Response response) throws JSONException, IOException {
        JSONObject jsonObj = new JSONObject(response.readEntity(String.class));
        ObjectMapper mapper = new ObjectMapper();
        JSONObject memberViewObj = (JSONObject)jsonObj.get("members");
        TypeReference<HashMap<String, T>> typeRef = new TypeReference<HashMap<String, T>>() {};        
        Map<String, T> map = mapper.readValue(memberViewObj.toString(), typeRef);
        return new ArrayList<>(map.values());
    }
I am calling in this way
List<ABC> nodes = ResponseUtil.getMemberViewRepresentation(response);

But the output of above method is not same. List is not of type ABC

@JsonIgnoreProperties(ignoreUnknown = true)
public class ABC {
    @JsonProperty("id")
    private int id;
    @JsonProperty("uid")
    private String uid;

    public int getId() {
        return id;
    }

    public String getUid() {
        return uid;
    }
}

Any idea how to keep the method dynamic such that i can pass Class details separately

I think, what you need is:

List<ABC> nodes = ResponseUtil.<ABC>getMemberViewRepresentation(response);

...to infer the generic parameter(s) into a static method (WITHOUT typed parameter(s)).

Note the extra <ABC> before method invocation! Normally you don't need it, because a regular generic method goes like: public static<T> void foo(T someInput) {...} ...and providing someInput , T is known/easy to infer at runtime. In your case Response has nothing to do with ABC ...so can't be inferred (with anything else than ? ).

The first method works as expected, because there is no "generic method", while the "class generic type" seems to be inferred correctly (somewhere else in your code/configuration).

The second doesn't, because the "generic method type" is missing (and i assume inferred as <?> respectively <java.lang.Object> ...so you get a List<Object> returned and assigned to your List<ABC> , which is not as expected, but at least "fail free").

You can argument, that we can "infer" ABC from the return type (you expect a List<ABC> , where a List<T> is delivered), but unfortunately this is not how it works /this information is not available at that point/needs deeper study.

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