users@jersey.java.net

Re: [Jersey] Polymorphic deserialization of JSON?

From: Chad McHenry <mchenryc_at_gmail.com>
Date: Sat, 9 May 2009 18:40:17 -0400

2009/5/9 Felipe Gaścho <fgaucho_at_gmail.com>

> I am doing that.. with subclasses of JPA entities.. it works ..
>
> like that:
>
> http://fgaucho.dyndns.org:8080/footprint-service/user/read/2
> http://fgaucho.dyndns.org:8080/footprint-service/user/edit/2
>
> notice the two service calls reads the same entity from the database,
> but in one path I have a partial view on the entity, while in the
> other path I have the complete representation...


Thanks for sharing your code Filipe. As I feared, I'm looking for a solution
to a different problem.

Using shapes as an example, I would like to be able to send POST and PUT
messages to a Jersey Resource which accepts a "Shape" as an argument, but
instead of deserializing a Shape, I would like the unmarshaller to recognize
the descriminator in the incoming data, and deserialize a Circle or
Rectangle.

So that I can POST both Circles and Rectangles to the same URL but the app
will deserialize the correct subtype:

This is what I would _like_ to see, but does not work yet.

class Shape { public String shapeType; }
class Circle extends Shape { public int radius; }
class Rectangle extends Foo { public int width; public int height; }

@Path("/shape")
class ShapeResource {
    ...
    @POST
    public Foo create(Shape shape) {
        log.debug(shape.getClass());
    }
    ....

curl -X POST -H 'Content-type: application/json' \
    -d '{"shapeType":"circle", "radius":33}' localhost/app/shape
[debug] Circle

curl -X POST -H 'Content-type: application/json' \
    -d '{"shapeType":"rectangle", "width":5, "height":3}
' localhost/app/shape
[debug] Rectangle

====

The issue I see is that by declaring a method that accepts a "Shape", the
JSON unmarshaller looks only for the properties of shape and discards the
interesting bits about rectangles and circles - which is why I can not use a
JAXB @XMLAdapter annotation.

I have considered separate URLs for each subtype, and may have to use them
if I cannot find a way to unmarshal the subclasses.

    @POST
    @Path("/rectangle")
    public Foo createRectangle(Rectangle shape) {
        log.debug(shape.getClass());
    }

    @POST
    @Path("/circle")
    public Foo createCircle(Rectangle shape) {
        log.debug(shape.getClass());
    }

curl -X POST -H 'Content-type: application/json' \
    -d '{"shapeType":"circle", "radius":33}' localhost/app/shape/circle
[debug] Circle

curl -X POST -H 'Content-type: application/json' \
    -d '{"shapeType":"rectangle", "width":5, "height":3}
' localhost/app/shape/rectangle
[debug] Rectangle





> I am trying to finish the articles about that.. despoite the flu and
> the time :) eheh
>
> Meanwhile, you can checkout my code from footprint:
>
> svn checkout https://footprint.dev.java.net/svn/footprint/trunk
> footprint --username guest
> cd footprint
> mvn clean install
>
> and then you have the EAR file in the footprint-service/target
> folder.. just start the database, the glassfish and then deploy this
> ear....
>
> and keep asking here if you like the solution and if you have
> questions about it......
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>