Jersey 序列化/反序列化问题:抽象类型只能使用附加类型信息进行实例化
我使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试this 它的工作原理
与 xml 相同
try this it works
it's the same with xml
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 definitionDetailOrder
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 typejava.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.如果您只想排除
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.htmlThat 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.