allenwoot
allenwoot

Reputation: 961

Get jersey to deserialize into subclass

I'm trying to get Jersey to automatically deserialize into a subclass instance of the declared class for me.

Say A has one string field named "a". B extends A has one string field named "b". Similarly, C extends A has one string field named "c".

I'd like for an input which has fields "a" and "b" to be deserialized into an instance of B, and an input which has fields "a" and "c" to be deserialized into an instance of C with one endpoint definition, specifying the post body parameter type as A, as follow.

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public ServerResponse translateClientRequest(final A postBody) throws 
ProxyException {
    ..
}

This example doesn't work. Is what I'm asking for possible? If so, how?

Upvotes: 0

Views: 1144

Answers (2)

futuretelematics
futuretelematics

Reputation: 1495

You probabily should have to use a custom response (or request) mapper.

1.- Create a class implementing MessageBodyReader in charge of writing / reading the request

@Provider
public class MyMessageBodyReader 
  implements MessageBodyReader<A> {
     @Override
     public boolean isReadable(final Class<?> type,final Type genericType,
                               final Annotation[] annotations,
                               final MediaType mediaType) {
         // you can check if the media type is JSon also but it's enougth to check 
         // if the type is a subclass of A
         return A.class.isAssignableFrom(type);  // is a subclass of A?
     }
     @Override
     public A readFrom(final Class<A> type,
                       final Type genericType,
                       final Annotation[] annotations,
                       final MediaType mediaType,
                       final MultivaluedMap<String,String> httpHeaders,
                       final InputStream entityStream) throws IOException,
                                                              WebApplicationException {
        // create an instance of B or C using Jackson to parse the entityStream (it's a POST method)        
    }
}

2.- Register the Mappers in your app

public class MyRESTApp 
     extends Application  {
    @Override
public Set<Class<?>> getClasses() {
        Set<Class<?>> s = new HashSet<Class<?>>();
        s.add(MyMessageBodyReader.class);
        return s;
    }
}

Jersey will scan all registered Mappers calling their isReadable() method until one returns true... if so, this MessageBodyReader instance will be used to serialize the content

Upvotes: 1

Kayaman
Kayaman

Reputation: 73558

Sounds like you want a custom MessageBodyReader that will determine the class and convert the data to appropriate subclass.

See JAX-RS Entity Providers for examples.

Upvotes: 0

Related Questions