8

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".

Danubian Sailor
  • 1
  • 38
  • 145
  • 223

3 Answers3

12

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})
nizar ouerghi
  • 1,721
  • 2
  • 14
  • 12
6

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.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • Im using @XmlSeeAlso to specify all inheriting classes (15 :-), without it serialization caused an error. Maybe weblogic add something, I don't know weblogic, I must just integrate with a project unfortunatelly made for him. – Danubian Sailor Jan 31 '12 at 08:44
  • Ah. Yes, `@XmlSeeAlso` is probably translated to equivalent of `@JsonTypeInfo`. That is fine -- it just also needs to be similarly visible. There is also possibility that JAXB annotation introspector extension (it's a Jackson add-on) could have a bug here. One possibility is to try using Jackson as stand-alone first, to see if things work outside of WebLogic, and depending on how that goes, find appropriate fix. – StaxMan Jan 31 '12 at 18:04
  • I've merged all 15 classes into one DTO, so first problem is away. But the class contains lists of objects, and for these @type tags are not generated, so deserialization also fails. – Danubian Sailor Feb 01 '12 at 10:16
  • You need to similarly annotate properties -- `@JsonTypeInfo` is not transitive (although it does apply to contents of Lists, when applied to a List property). – StaxMan Feb 01 '12 at 18:41
1

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.