Using JERSEY and JACKSON to parse a POST request with unknown structure - java

I'm in a current situations in which I have a REST endpoint that accepts POST of incoming JSON messages.
The thing is that I don't think I can specify the POJO object so Jackson can marshall the JSON into the POJO object. Reason for this is that I don't have control of what comes to that endpoint, and number of fields and type can change over time, thus, defining a POJO before hand seems not an option.
So I guess the question is....can I simply tell Jackson to don't do any marshalling and give the String of the response? I can deal with that later with JSONObject-JSONArray or Gson maybe. Say I'd have a method like this:
#POST
#Path("/callback")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response facebookUpdate(String json) {
//Do something with the json response...
}
If this is not feasible with Jersey-JAX...any other alternatives?
Thanks!
Alejandro

The easiest is to simply not inject the json into the method and use the request object instead:
public Response facebookUpdate(#Context request) {
try(InputStream is=request.getEntityInputStream()) {
...
}
}
From the request you can then get an inputstream for the request and parse it whichever way you like.
For parsing I can recommend my own jsonj library, which was written specifically to support open ended scenarios like you describe and uses jackson to deserialize into heavily customised implementations of java.util.Map and java.util.List. Gson is also a very solid choice.
If you want to do this application wide, you can instead write your own #Provider and do the same there. This is how I use my library currently actually.

Related

Vertx model binding for my Rest API layer

I'm using Vertx 3, and I'm trying to find a good decoupled module that knows to turn query-string, headers and both content-type and body into a bean?
I know spring does that and various other frameworks as well, but I don't want to introduce a new framework i just want a super fast model binder that will either know to auto bind to a certain method or at least auto bind a certain class so i can invoke my rest method that currently accept one parameter, which is the model.
public ResponseBase query(QueryRequest model){ ... }
I don't mind adding annotations to the parameters etc.
Thanks!
Current my team use vertx Json.decodeValue to turn body (json string) to java class.
MyClass body = Json.decodeValue(rc.getBodyAsString(), MyClass.class);
to config Json to handle unknown properties, I setting
Json.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
for your query string, I think it is easy to write a class to convert it to a json string :)
I also catch DecodeException on Json.decodeValue to re throw a 400 Bad Request error.

How to convert JSON to list of POJOs using RestEasy

I have to integrate our j2ee application with a REST webservice. And I wanted to use the RestEasy JAX-RS implementation from JBoss. The webservice returns an array in JSON format. I've this piece of code:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://myservices.com/schemes/all");
Response response = target.request().get();
Can I map this "response" object to List<Scheme> using RestEasy? Thanks
Provided that your JSON provider is capable of converting JSON to appropriate entities, then yes. The get method you call in the code has an overloaded version which accepts the class of entity to which the result is to be converted. Since there are problems with serializing certain collections' implementations, your type has to be wrapped in GenericType class, like that:
List<Scheme> schema = [...].get(new GenericType<List<Scheme>>(){});
The above method should work with just about every JAX-RS-compliant implementation.
You can also use Jackson library, which allows you (amongst other things) to pass collections without need of wrapping them.

retrieve data from post in JAX-RS

The server is sending data in JSON as HTTP POST, and I am using jax-rs to handle and retrieve data.
I could use #Pathparam or #queryparam based on what I wanted, but data doesnt like in either of those. Not in header either, if I am right, as they content something like content-type, date and some similar sort. How do I retrieve data from POST?
#POST
#Path("/foo")
public void foo(){ //do i need to put sth in parameter paranthesis to get?
//handle the data!! but how??
}
I suggest you take a look at JAX-RS Entity Providers. I will explain to you how marshalling and unmarshalling is done to and from the response and request stream, respectively.
Basically you have MessageBodyReaders and MessageBodyWriters (the former being the one the unmarshall from the request stream. How is works say you have a method like so
#POST
#Consumes(MediaType.TEXT_PLAIN)
public Response postString(String s) {}
The String s, like any other method parameter without an annotation is treated as the body of the request. (Note a method can only have one non-annotated parameter; that is a request can only have one body). So what happens is the JAX-RS (implementation's) runtime will look through the registry of providers (MessageBodyReaders to be exact) to look for one that can handle unmarshalling a body of type text/plain into a String. There are some standard readers for some standard types, and this is one that is available for free.
Now in the case of JSON, say we have this
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response postJson(String json) {}
This can be done also because there is a writer that can handle this. Basically a String parameters can be handled most of the time. It is not difficult to make an InputStream into a String, a String parameter we will usually get support for free.
But what if we want unmarshal to a different type, say Foo
class Foo {
String bar;
String baz;
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response postJson(Foo foo) {}
And we had JSON like
{ "bar" : "barValue", "baz": "bazValue" }
We can do this, but we need a custom reader. Luckily there are some already out there. We just need to add the library dependency to out project. For example, Jackson (I'd say the de facto JSON processor in Java) has a reader for us. It's in the dependency
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.0</version>
</dependency>
We can just register the JacksonJsonProvider into our application. Then we will be able to use POJOs from our JSON. (For more help on registering this, please provider more information about what JAX-RS implementation you are using, and show your application configuration, whether it's web.xml or Java config)
Some Resources:
See an answer here that describes Jackson use better (with documentation)
See here if you are confused about the #Consumes annotation

#Consumes(MediaType.APPLICATION_JSON) annotation but getting request body as string

I am currently working on a project which was maintained by some other team and now i need to maintain it. While i was going through the project i found some thing below:
In jax-rs controller it was annotated by #Consumes(MediaType.APPLICATION_JSON) but the method takes request body as String rather than JSON. Then what is the use of the annotation? Does it help in content negotiation anyway?
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createCake(final String requestBody){.......}
How it is converting a JSON body to string?
My technology stack if it anyway helps to answer:
JAX-RS
Spring 3.2
Jersey 2.4
The #Consumes serves the following purpose. It restricts the mapping for your handlers. For example, you may have two handlers for the path /resource, one mapped to consume XML and the other mapped to consume json. The dispatcher will choose the right one based on the request's content-type.
The parameter type can be anything as long as there is an appropriate converter for the specified media type to the parameter type itself. In this case, there's very likely a converter from any media type to String.

Apache Camel: Convert JSON to a POJO using Camel methods

I have a REST server which sends JSON in response body. I have recently started reading about Apache Camel. I use following to send requests to my REST service.
from("direct:start").setHeader("token", simple("234da"))
.to("http://localhost:8088/foo/bar/?foo1=bar1");
Now the response will be a JSON, is there any way I get this JSON directly into a POJO using some method ahead of to() (something like this)?
to("http://localhost:8088/foo/bar/?foo1=bar1").toPOJO();
I would prefer a non Spring solution.
Thanks
Little details from my side - although late
Create jsonFormatter and then unmarshal with class you need
JsonDataFormat jsonDataFormat = new JsonDataFormat(JsonLibrary.Jackson);
this can be used in marshalling
from("direct:consume-rest")
.log("calling bean method...")
.to("http://localhost:8080/greeting?name=baba")
//.process(svProcessor) // any extra process if you want
.unmarshal().json(JsonLibrary.Jackson, Greeting.class)
.bean(GreetingHelper.class, "print")
.log("converted to bean ...")
.end()
;
Helper class method
public void print (#Body Greeting greeting) {
Apache Camel provides a component to marshal and unmarshal POJO to and from JSON.
In your case, it would be :
from("direct:start").setHeader("token", simple("234da"))
.to("http://localhost:8088/foo/bar/?foo1=bar1")
.unmarshal().json();
By the way, you may need to configure your json library to do it and I suggest you take look at the official configuration.

Categories

Resources