Java generic bi-function to return value based on specified class type

tarunkumar :

I am trying to write generic Json deserializer as below,

  public static <T> BiFunction<String, Class<T>, T> jsonDeSerializer() {
    return (o, c) -> {
      try {
        return mapper.readValue(o, c);
      } catch (IOException e) {
        logger.error("json.parse.error object.type={}", o.getClass().getSimpleName(), e);
        throw new JsonProcessingEx(e);
      }
    };
  }

When trying to call, I am getting

error: incompatible types: Class<MLAdhocResponseVO> cannot be converted to Class<Object>
    MLAdhocResponseVO response = JsonUtils.jsonDeSerializer().apply("{}", MLAdhocResponseVO.class);

All I want to to write a BiFunction which returns Object based on provided class without need of any typecasting.

ernest_k :

When you call

JsonUtils.jsonDeSerializer().apply("{}", MLAdhocResponseVO.class);

jsonDeSerializer()'s generic type argument is Object (this and this can shed more light), not MLAdhocResponseVO as you seem to expect.

The quick fix is to add a type witness to the call, to tell the compiler what your intended type argument for the method is:

MLAdhocResponseVO response = JsonUtils.<MLAdhocResponseVO>jsonDeSerializer()
        .apply("{}", MLAdhocResponseVO.class);

Alternatively, you can give the compiler a target type by declaring a typed BiFunction variable:

BiFunction<String, Class<MLAdhocResponseVO>, MLAdhocResponseVO> 
                        function = jsonDeSerializer();
MLAdhocResponseVO response = function.apply("{}", MLAdhocResponseVO.class);

If you want to avoid this altogether, then your method may be better designed with an actual parameter of the generic type, which will assist the compiler's type inference:

public static <T> Function<String, T> jsonDeSerializer(Class<T> c) {
    return (o) -> {
        try {
            return mapper.readValue(o, c);
        } catch (IOException e) {
            logger.error("json.parse.error object.type={}", 
                   o.getClass().getSimpleName(), e);
            throw new JsonProcessingEx();
        }
    };
}

This way, your code compiles without needing a type witness:

MLAdhocResponseVO response = JsonUtils.jsonDeSerializer(MLAdhocResponseVO.class)
    .apply("{}");

And even this standalone expression is correctly typed:

JsonUtils.jsonDeSerializer(MLAdhocResponseVO.class)
        .apply("{}");

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=415104&siteId=1