Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST. Jersey. How to programmatically choose what type to return: JSON or XML?

I have 2 questions:

1. Can I create one class, annotate it with JAXB annotations(for XML support) and declare in web.xml

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

for JSON (Jackson library) support? Or I need to create separately two classes for JSON and XML?

Or may be exist some more elegant way to cause REST service to return both JSON and XML?

2. How I can programmatically choose what type to return (JSON or XML)?

Thanks.

like image 481
WelcomeTo Avatar asked Jul 08 '12 09:07

WelcomeTo


People also ask

CAN REST API use XML and JSON?

The same resource may return either XML or JSON depending upon the request, but it shouldn't return both at the same time. You will know which one to return based upon the request, so there is no need to generate both -- just generate the one you'll be returning.

CAN REST API return XML?

Data types that REST API can return are as follows: JSON (JavaScript Object Notation) XML. HTML.

Which of the following annotation would allow request parameters to be converted into JSON XML type?

When we use the @RequestBody to annotate the method argument we are telling the framework to convert the JSON or XML payload which is in the request body of HTTP request into the object of a given type.

In which of the following the returned object is directly written in HTTP response as JSON or XML?

Spring MVC Framework and REST While the traditional MVC controller relies on the View technology, the RESTful web service controller simply returns the object and the object data is written directly to the HTTP response as JSON/XML.


3 Answers

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.


Can I create one class, annotate it with JAXB annotations(for XML support) and declare in web.xml for JSON (Jackson library) support?

You can always use an Application class to specify a MessageBodyReader/MessageBodyWriter for the JSON binding. I believe Jackson provides an implementation in its jar. Below is an example of an Application class that specifies MOXy as the JSON provider:

package org.example;

import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;

public class CustomerApplication  extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>(2);
        set.add(MOXyJsonProvider.class);
        set.add(CustomerService.class);
        return set;
    }

}

Or I need to create separately two classes for JSON and XML?

EclipseLink JAXB (MOXy) offers native XML binding and is designed to enable you to use the same object model for both JSON and XML. You can integrate it into your JAX-RS application using the MOXyJsonProvider class:

  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html

How I can programmatically choose what type to return (JSON or XML)?

Server Side

You can specify that your service offers both XML and JSON messages using the @Produces annotation.

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Path("{id}")
public Customer read(@PathParam("id") long id) {
    return entityManager.find(Customer.class, id);
}

For More Information

  • http://blog.bdoughan.com/2012/03/moxy-as-your-jax-rs-json-provider.html

Client Side

You can use the MediaType to indicate the type of message. Below is an example using Jersey client APIs. Note how the URL is the same, just the requested media type is different.

Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080/CustomerService/rest/customers");

// Get XML response as a Customer
Customer customer = resource.path("1")
    .accept(MediaType.APPLICATION_XML)
        .get(Customer.class);
System.out.println(customer.getLastName() + ", "+ customer.getFirstName());

// Get JSON response as a Customer
Customer customer = resource.path("1")
    .accept(MediaType.APPLICATION_JSON)
        .get(Customer.class);
System.out.println(customer.getLastName() + ", "+ customer.getFirstName());

For More Information

  • http://blog.bdoughan.com/2010/08/creating-restful-web-service-part-55.html
like image 188
bdoughan Avatar answered Oct 09 '22 03:10

bdoughan


If your client wants to use a part of the URL to configure the response type, you can use a Servlet filter.

An easy way to implement overriding the representation (media type) could use a URL query parameter:

/resources/todo?format=json

The Servlet filter parses the URL query parameters, and if a format=json is present, replaces or adds the accept header "application/json".

like image 34
mjn Avatar answered Oct 09 '22 05:10

mjn


No need for seperate classes, what you need is seperate methods:

@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Todo getXML() {
    Todo todo = new Todo();
    todo.setSummary("This is my first todo");
    todo.setDescription("This is my first todo");
    return todo;
}

Then in the client side, when you request for the service, you indicate in what format you want it:

// Get XML
System.out.println(service.path("rest").path("todo").accept(MediaType.TEXT_XML).get(String.class));
// Get XML for application
System.out.println(service.path("rest").path("todo").accept(MediaType.APPLICATION_XML).get(String.class));
// Get JSON for application
System.out.println(service.path("rest").path("todo").accept(MediaType.APPLICATION_JSON).get(String.class));
like image 38
Tomer Avatar answered Oct 09 '22 04:10

Tomer