Jersey 序列化/反序列化问题:抽象类型只能使用附加类型信息进行实例化

发布于 2024-12-31 21:33:46 字数 2699 浏览 1 评论 0原文

我使用 jersey 进行序列化和反序列化。我已经使用 jersey 在 WebLogic 上创建了 REST 通道。我有包含抽象类的结果对象。 Jersey 使用此类的实现名称添加到结果元数据中:

{"order":{"@type":"installationOrder",

但是,同一个 jersey 在用于反序列化此数据时,会发出以下尖叫声:

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of ocl.mobile.service.data.order.DetailedOrder, problem: abstract types can only be instantiated with additional type information
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@97eded; line: 1, column: 2] (through reference chain: ocl.mobile.service.OrderDetailsResult["order"])
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
    at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:252)
    at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
    at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2376)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1166)
    at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:410)
    at com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy.readFrom(JacksonProviderProxy.java:139)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:553)
    ... 5 more

但他本人在他序列化的 JSON 中提供了此附加信息。

那么,如何让 jersey 能够阅读并理解他创建的这个“@type”注释呢?

这就是我使用 jersey 从通道读取数据的方式:

private static Client client;

private static void initClient() {
    if (client == null) {
        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
                Boolean.TRUE);
        client = Client.create(clientConfig);
    }
}

private static <T> T jsonForResult(String addr, Class<T> expectedClass) {
    initClient();
    WebResource r = client.resource(addr);
    try {
        T result = r.get(expectedClass);
    return result;
        } catch (UniformInterfaceException e) {
        log.error(e.getMessage(), e);
        return null;
    }
}

在我的例子中,expectedClass 是结果类,其中包含状态和抽象类“order”,它具有“installationOrder”等实现。

I'm using jersey for both serialization and deserialization. I've made REST channel on WebLogic using jersey. I have result object with contains abstract class. Jersey adds to the result metadata with this class'es implementation name:

{"order":{"@type":"installationOrder",

However, the same jersey, when using to deserialize this data, is screaming the following:

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of ocl.mobile.service.data.order.DetailedOrder, problem: abstract types can only be instantiated with additional type information
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@97eded; line: 1, column: 2] (through reference chain: ocl.mobile.service.OrderDetailsResult["order"])
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
    at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
    at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:252)
    at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
    at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2376)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1166)
    at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:410)
    at com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy.readFrom(JacksonProviderProxy.java:139)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:553)
    ... 5 more

but he himself have provided this additional information in the JSON he has serialized.

So, how to make jersey to read and understand this "@type" annotations he have created?

This is how I'm using jersey to read data from channel:

private static Client client;

private static void initClient() {
    if (client == null) {
        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
                Boolean.TRUE);
        client = Client.create(clientConfig);
    }
}

private static <T> T jsonForResult(String addr, Class<T> expectedClass) {
    initClient();
    WebResource r = client.resource(addr);
    try {
        T result = r.get(expectedClass);
    return result;
        } catch (UniformInterfaceException e) {
        log.error(e.getMessage(), e);
        return null;
    }
}

The expectedClass is in my case the class of result, which contains status and the abstract class "order", which has implementations such as "installationOrder".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鹊巢 2025-01-07 21:33:46

尝试this 它的工作原理

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ExchangeFormat.class, name = "ExchangeFormat"),
@JsonSubTypes.Type(value = TypeStatus.class, name = "TypeStatus"),
})
public abstract class MapperJsonXml <T>

与 xml 相同

@XmlSeeAlso({ExchangeFormat.class,TypeStatus.class})

try this it works

@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ExchangeFormat.class, name = "ExchangeFormat"),
@JsonSubTypes.Type(value = TypeStatus.class, name = "TypeStatus"),
})
public abstract class MapperJsonXml <T>

it's the same with xml

@XmlSeeAlso({ExchangeFormat.class,TypeStatus.class})
只是一片海 2025-01-07 21:33:46

Jersey(或更具体地说,它与 POJO 映射一起使用的 Jackson JSON lib)不会添加 @type ,除非启用类型信息包含,通常通过在抽象类型上添加 @JsonTypeInfo 来实现。所以一定是有什么东西促成了这一点。也许您可以共享定义 DetailOrder 类?

至于问题本身:这通常是由使用的不兼容类型引起的——用于反序列化(将 JSON 值读入 POJO)的类型必须使得 @JsonTypeInfo 注释可见。例如,您不能只请求 java.lang.Object 类型的值,因为它没有这样的注释。如果不知道实际的类定义,就不可能指出具体原因,但这是最可能的解释。

Jersey (or more specifically, Jackson JSON lib it uses with POJO mapping) does not add @type unless type information inclusion is enabled, usually by adding @JsonTypeInfo on an abstract type. So something must have enabled this. Maybe you can share definition DetailOrder class?

As to problem itself: this is usually caused by incompatible types used -- type used for deserialization (reading JSON value into POJO) must be such that @JsonTypeInfo annotation is visible. You can not, for example, just ask for value of type java.lang.Object, since it does not have such annotation. Without knowing actual class definitions it is not possible to point to specific cause, but this is the most likely explanation.

ゃ懵逼小萝莉 2025-01-07 21:33:46

如果您只想排除 type 字段,请注释超类 @XmlTransient,如下所述:http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html

这将使序列化工作就像超类字段位于子类中一样 -因此就好像没有继承一样,在这种情况下将不会生成 type 字段。

If you just want to just exclude type field, annotate the superclass @XmlTransient, as mentioned here: http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html

That will make the serialization work as if the superclass fields were in the child class - thus as if there was no inheritance, in which case the type field won't be produced.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文