Java jax-rs 客户端响应实体通用

Java jax-rs client response entity generic

我对通用函数有疑问。我想使用一个函数,我为其分配了某个 class / 类型,首先从休息响应生成相应的结果,然后 return 它。

public class TimerService {

    [...]

    public <T extends myObjInterface> RestMessageContainer<T> send(String endpointPath, Map<String, String> parameters, Class<T> clazz) {
        [...]
        Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE).get();
        RestMessageContainer<T> container = response.readEntity(new GenericType<RestMessageContainer<T>>() {});
        return container;
    }
}

public class RestMessageContainer<T extends myObjInterface> {

    [...]

    @XmlAttribute(name = "data")
    private List<T> data;

    [...]
}

我在运行时收到以下错误消息。

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct     instance of `com.test.myObjInterface` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
14:47:41,982 ERROR [stderr] (EJB default - 2)  at [Source: (org.jboss.resteasy.client.jaxrs.internal.ClientResponse$InputStreamWrapper); line: 3, column: 14] (through reference chain: com.test.RestMessageContainer["data"]->java.util.ArrayList[0])

RestMessageContainer<T> container = response.readEntity(new GenericType<RestMessageContainer<T>>() {});

行输出错误

我的方法是否完全正确或者我应该如何解决我的问题?

您不能创建抽象的实例 class。不过,你可以通过一个简单的注解来解决问题——@JsonDeserialize on the abstract class:

@JsonDeserialize(as = Cat.class)
abstract class Animal {...}

在您的情况下,摘要 class 将是 myObjInterface

注意:如果您有多个子类型的摘要 class,那么您应该考虑包含子类型信息,如此 post.

感谢您的建议, 我有几个子类。 JSON 字符串中没有关于类型的信息。该类型来自请求地址。我无法配置 Jackson 来识别子类型。 JSON 字符串中没有可用作类型的唯一字段。 我无法更改提供 JSON 字符串的 Web 服务。


[更新]

我找到了解决办法。我不再让 JAX-RS 客户端转换 JSON 字符串。我将 JSON 字符串作为字符串返回给我,并使用 Jackson 独立转换它。

    public <T extends myObjInterface> RestMessageContainer<T> send(String endpointPath, Map<String, String> parameters, Class<T> clazz) {
        [...]
        Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE).get();

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        RestMessageContainer<T> container = mapper.readValue(response.readEntity(String.class), mapper.getTypeFactory().constructParametricType(RestMessageContainer.class, clazz));

        return container;
    }