Convert from JSON with Jackson Annotations - java

I am attempting to convert JSON into a Java object with the Play framework. I do not have easy control over the input JSON, which contains dashes in the names.
{ "field-name": "value" }
As a result, I cannot create a Java object with a default mapping to the JSON. I have a class which looks like this:
import com.fasterxml.jackson.annotation.JsonProperty;
public class Data {
#JsonProperty("field-name")
public String fieldName;
}
I know that Play 2.4 uses Jackson, and
I have a unit test which is able to populate the object from the JSON using a default Jackson ObjectMapper.
The JSON is the body of a POST request, and I attempt to use it like this:
Form<Data> form = Form.form(Data.class).bindFromRequest();
If I print form, I can that the data field is populated with the expected values. However, when I do form.get(), the returned value has a null field. (In the actual code, there are more fields, which are Strings or longs. All of them are null or 0.)
Am I attempting to customize the JSON deserialization in the wrong way? Or am I doing something else wrong?

As you've expected you've used the wrong way to deserialize. The Forms class is for PlayForms only and not for Json request. Have a look at the BodyParser and JsonActions documentation:
#BodyParser.Of(BodyParser.Json.class)
public Result index() {
RequestBody body = request().body();
Data data = Json.fromJson(body.asJson(), Data.class);
return ok("Got java object: " + data.toString());
}

Related

Marshall object returned by #RequestBody

I have XML being fed into a REST controller and I use the #RequestBody annotation to transform that into a Java Object. I need to save the whole XML to a database column in addition to some specific elements from the Java Object. I am marshalling the Java object explicitly to accomplish this and that seems to be duplicate work. Is there a way to get the raw XML in addition to the parsed object while using the #RequestBody annotation?
Yes, there is. Let's say this is your controller method:
public Response yourControllerMethod(#RequestBody YourDTO dto) {
Simply change your #RequestBody parameter type to String and you'll get the raw body of the request:
public Response yourControllerMethod(#RequestBody String rawPayload) {
Or you can even get both:
public Response yourControllerMethod(#RequestBody YourDTO dto, #RequestBody String rawPayload) {

Is there any way to create JSON object with keys as upper case?

Project: Android app using REST web service
Using:
Client - Volley
Server API - Jersey
Converter: Gson
This is my first time asking a question here, and i will provide my way of "evading" this code convention. Since i am working on a project where POJO fields are already defined as upper-case (sadly, i cant change that), i had to find a way to fix JSON string and convert it to an instance of uppercase POJO.
So basicaly its: client POJO <--> json object converted to/from gson <--> server POJO
So, lets say that i have a field in Users.class
String USERNAME;
When Jersey sends an instance of via #Produces, it follows the convention of creating JSON and sends an object
{"username": "random_name"}
When it gets converted from JSON via gson.fromJSON, an instance of a client's POJO will get null value for that field (obviously because field is in lower-case in JSONObject).
This is how i managed it by using a method that parses JSONObject and puts each key as upper-case:
public static String fixJSONObject(JSONObject obj) {
String jsonString = obj.toString();
for(int i = 0; i<obj.names().length(); i++){
try{
obj.names().getString(i).toUpperCase());
jsonString=jsonString.replace(obj.names().getString(i),
obj.names().getString(i).toUpperCase());
} catch(JSONException e) {
e.printStackTrace();
}
}
return jsonString;
}
And luckily since gson.fromJSON() requires String (not a JSONObject) as a parameter besides Class, i managed to solve the problem this way.
So, my question would be: Is there any elegant way of making JSON ignore that code convention and create a JSON object with an exact field? In this case:
{"USERNAME": "random_name"}
Jersey uses JAXB internally to marshall beans to xml/json. So you can always use #XmlElement annotation and use name attribute to set the attribute name to be used for marshalling
#XmlElement(name="USERNAME")
String USERNAME;
Just use annotation com.google.gson.annotations.SerializedName
Add in class Users.java:
#SerializedName("username")
String USERNAME;

Incongruity between Cloudify documentation for a REST response and the one I get

I have a Cloudify 2.7.0 instance running.
I need to access Cloudify's API from a Java application and I found an incongruity between the returned JSON and the one which is documented in the Cloudify documentation.
The API is
/service/applications
In the documentation I can read that it should return the following JSON string
{
"status" : "success",
"response" : [ "petclinic", "travel" ]
}
But if I do the same request to my Cloudify instance I get the following JSON string
{
"status" : "success",
"response" : {
"petclinic": "",
"travel":""
}
}
In the java application the JSON information is stored in the following POJO (generated with JSONSchema2POJO)
// CloudifyResponse.java
public class CloudifyResponse {
#JsonProperty("response")
private Response response;
#JsonProperty("status")
private String status;
// getters and setters
}
// Response.java
public class Response {
#JsonProperty("helloworld")
private String helloworld;
#JsonProperty("petclinic")
private String petclinic;
// getters and setters
}
I use the Jackson library to deserialize JSON into POJO. As you can see the JSON string is deserialized into a POJO in which every istantiated application is a POJO's field.
This might be a big problem for the development of the application. In fact, as the instances of the application change, the returned JSON changes and we need to update the POJO structure, something I can't do at runtime.
Do you know whether the Cloudify API has changed the response JSON structure? Is there any way to get the documented JSON output instead of the one I get.
Thank you in advance
Giulio
As of 2.7 The service controller (which you are referring to here) is deprecated, and actually remains available for backward compatibility. The documentation is indeed wrong regarding the returned json structure.
My advice is to use the updated API
/{version}/deployments/applications/description
As documented here, this API actually returns a json holding a list of ApplicationDescription objects, so as application are deployed the response structure remains essentially the same, but the contained list grows.

Unmarshal nested JSON object to generic Java object

I'm using Jersey (2.5.1) for a RESTish API with JAXB to marshal JSON to/from POJOs. The client will be doing a POST with the following request:
{
"type":"myevent",
"data":{
"id":"123",
"count":2
}
}
I have an 'Event' class which holds a type string and a data payload.
#XmlRootElement
public class Event {
#XmlElement public String type;
#XmlElement public JSONObject data;
...
}
The 'data' payload is a JSON object, however I don't know what type, or what the 'schema' of the object is. All I know is it's JSON. Above I have the type as a JSONObject, but that's just an example, maybe this needs to be Object? Map? Something else?
I want to be able to get the 'data' payload and persist this as JSON somewhere else.
I thought about using a String for the data payload, but then any API client would need to encode this and I would need to decode it before passing it on.
Any suggestions?
I usually work with strings on the backend side and then
JSONObject json = new JSONObject(s);
would create a json obj from that s (you don't need to decode).
On the client side I believe you just need to escape the " with something like a replaceAll function applied on that string

How can I proccess Json faster than creating bean objects manually

For example, at the moment I am getting a list of restaurants from a Google API. then I have to create a a restaurant class with getters and setters, then I have to create objects of that class and populate them with each field from the returned json manually.
Is there another way to do this quicker than manually doing all the work?
The best thing is to find libraries for that particular API. Failing that, you could consume the JSON without mapping them to Java Beans (i.e. just parse the JSON and work with the parsed JSON by doing parsed.getString("city_name") etc.). Jackson is a good library to do that.
You could also try generating a JSON schema out of the returned JSON, then using that to auto generate Java Beans code, and then use this with a JSON library like Jackson. I tried this once but it seems that you have to fix the generated JSON schema quite a bit as the automatic schema generation tools referenced above isn't very good at the moment.
What I do is just create an object that matches the returned json string and place the values into the object using gson.fromjson()
Object.
public class Return {
private String Status;
private String[] Data;
public Return(String Status, String[] Data){
this.Status=Status;
this.Data=Data;
}
public String getStatus() { return Status; }
public String[] getData() { return Data; }
}
Code to populate Object.
java.lang.reflect.Type listType = new TypeToken<Return>(){}.getType();
Return return2= new Gson().fromJson(myresponse.toString(), listType);

Categories

Resources