Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consuming JSON object in Jersey service

Tags:

json

jersey

I've been Googling my butt off trying to find out how to do this: I have a Jersey REST service. The request that invokes the REST service contains a JSON object. My question is, from the Jersey POST method implementation, how can I get access to the JSON that is in the body of the HTTP request?

Any tips, tricks, pointers to sample code would be greatly appreciated.

Thanks...

--Steve

like image 628
Steve Avatar asked Nov 02 '09 17:11

Steve


People also ask

How do I get JSON request in Jersey?

if you want your json as an Vote object then simple use @RequestBody Vote body in your mathod argument , Spring will automatically convert your Json in Vote Object.

What type of JSON support is available in Jersey?

Jersey JSON support comes as a set of JAX-RS MessageBodyReader<T> and MessageBodyWriter<T> providers distributed with jersey-json module. These providers enable using three basic approaches when working with JSON format: POJO support.

Does Jersey use Jackson?

Jersey uses Jackson internally to convert Java objects to JSON and vice versa.


1 Answers

As already suggested, changing the @Consumes Content-Type to text/plain will work, but it doesn't seem right from an REST API point of view.

Imagine your customer having to POST JSON to your API but needing to specify the Content-Type header as text/plain. It's not clean in my opinion. In simple terms, if your API accepts JSON then the request header should specify Content-Type: application/json.

In order to accept JSON but serialize it into a String object rather than a POJO you can implement a custom MessageBodyReader. Doing it this way is just as easy, and you won't have to compromise on your API spec.

It's worth reading the docs for MessageBodyReader so you know exactly how it works. This is how I did it:

Step 1. Implement a custom MessageBodyReader

@Provider @Consumes("application/json") public class CustomJsonReader<T> implements MessageBodyReader<T> {   @Override   public boolean isReadable(Class<?> type, Type genericType,       Annotation[] annotations,MediaType mediaType) {     return true;   }    @Override   public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,       MediaType mediaType, MultivaluedMap<String, String> httpHeaders,       InputStream entityStream) throws IOException, WebApplicationException {      /* Copy the input stream to String. Do this however you like.      * Here I use Commons IOUtils.      */     StringWriter writer = new StringWriter();     IOUtils.copy(entityStream, writer, "UTF-8");     String json = writer.toString();      /* if the input stream is expected to be deserialized into a String,      * then just cast it      */     if (String.class == genericType)       return type.cast(json);      /* Otherwise, deserialize the JSON into a POJO type.      * You can use whatever JSON library you want, here's      * a simply example using GSON.      */     return new Gson().fromJson(json, genericType);   } }

The basic concept above is to check if the input stream is expected to be converted to a String (specified by Type genericType). If so, then simply cast the JSON into the specified type (which will be a String). If the expected type is some sort of POJO, then use a JSON library (e.g. Jackson or GSON) to deserialize it to a POJO.

Step 2. Bind your MessageBodyReader

This depends on what framework you're using. I find that Guice and Jersey work well together. Here's how I bind my MessageBodyReader in Guice:

In my JerseyServletModule I bind the reader like so --

bind(CustomJsonReader.class).in(Scopes.SINGLETON);

The above CustomJsonReader will deserialize JSON payloads into POJOs as well as, if you simply want the raw JSON, String objects.

The benefit of doing it this way is that it will accept Content-Type: application/json. In other words, your request handler can be set to consume JSON, which seems proper:

@POST @Path("/stuff") @Consumes("application/json")  public void doStuff(String json) {   /* do stuff with the json string */   return; }
like image 122
pestrella Avatar answered Sep 30 '22 08:09

pestrella