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".
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})
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With