XML & JSON web api : automatic mapping from POJOs?

2019-03-06 12:28发布

问题:

I'm about to start on a small project which goal is to end up with a web xml/json api. I'll be writing it in Java, and I'll be using the restlet library.

How do I approach the xml/json duality? I know I can use JAXB to "convert" pojos to xml (and back), but how do I automate this for json? Is there any functionality in the restlet library I can leverage?

回答1:

Restlet allows you to directly work with POJOs within your server resources at the level of REST annotated methods, as described below:

public class MyServerResource extends ServerResource {
    @Get
    public List<MyPojo> getList() {
        List<MyPojo> list = (get list from backend for example)
        return list;
    }

    @Post
    public MyPojo addPojo(Pojo pojo) {
        addPojoInBackend(pojo

        getResponse().setLocationRef(getUri() + field.getId());
        getResponse().setStatus(Status.SUCCESS_CREATED);

        return pojo;
    }
}

You don't need to specify media type (i.e. content type) within the content of the annotations.

To handle such code, Restlet provides a generic conversion feature that does the work under the hood. Restlet extensions provide different implementations for this feature. If you want to have both XML and JSON for your RESTful application, I think that you should the Jackson extension for what you want to do. Jackson (http://wiki.fasterxml.com/JacksonHome) is a tool that allows to convert POJO to various formats like XML, JSON and YAML.

To enable this, simply put the JAR file of the Jackson extension (org.restlet.ext.jackson) in your classpath and use the programming approach described above. Here are the details on how it works:

  • You will be able to send both JSON and XML content (set the header Content-Type in the request) and Restlet will automatically convert this content to the bean expected in the annotated method.

    POST /myresource
    Content-type: application/json
    { "id":"myid", ... }
    
  • To switch / select the expected content with response, you can leverage to conneg (content negociation of REST) based on the header Accept. If you specify application/json, a JSON content wil be received and applicaiton/xml, a XML one.

    GET /myresource
    Accept: application/json
    { "id":"myid", ... }
    
    GET /myresource
    Accept: application/xml
    <elt><id>myid> ... </elt>
    
  • You can notice that Restlet also support a query parameter media (not standard) to select the content to receive. If you specify json, a JSON content will be received back and xml an XML one.

    GET /myresource?media=json
    { "id":"myid", ... }
    
    GET /myresource?media=xml
    <elt><id>myid> ... </elt>
    

To finish, you can notice that this mechanism is also supported on server-side with Restlet. This means that you can work directly with beans. This feature can be used with Restlet annotated interfaces, as described below:

public interface MyResource {
    @Get
    List<MyPojo> getList();

    @Post
    MyPojo addPojo(Pojo pojo);
}

You can use this interface as described below:

ClientResource cr = new ClientResource("http://(...)/myresource");
MyResource myResource = cr.wrap(MyResource.class);
// List
List<Pojo> list = myResource.getList();
// Add
Pojo pojo = new Pojo();
pojo.setId("myid"); // for example
(...)
Pojo returnedPojo = myResource.add(pojo);

Don' forget to put in the client classpath application the extension Jackson.

Hope it helps, Thierry