Mapping Dynamic Json response(has changing attributes) using Jackson - java

I am trying to map Json response whose attributes changes if there is any error. For example:
valid response :
{
"Header":[{
//some data
}],
"Component":[{
//data
}],
"ServiceParameter":[{
//data
}]
}
error response:
{
"Header":[{
//some data
}],
"ErrorMessage":[{
//data
}],
"ServiceParameter":[{
//data
}]
}
How can I map(with Jackson if possible) component data or error message for the given response ?

I can only think of having both fields included in your POJO, like this:
class JsonResponse {
#JsonProperty("Headers")
private List<Header> headers;
#JsonProperty("Component")
private List<Component> components;
#JsonProperty("ErrorMessage")
private List<ErrorMessages> errorMessages;
#JsonProperty("ServiceParameters")
private List<ServiceParameters> serviceParameters;
// Getters and setters
}
You can then know whether it's an error or not by checking if the errorMessages list is empty or not.
Jackson is a very flexible JSON (de)serializer, so it's very likely there's a way to do it, but this one is definitely the easiest one!

Related

Java GSON Json partial parsing

Say I have a JSON object representing an entity (can be any entity) like so:
{
"entity_id": "1",
"entity_name": "employee",
"entity_json": {
"employee_id": "e01",
"employee_name": "john",
"employee_phone_numbers": [
"1234567",
"8765433"
]
}
}
Note that entity_json can represent different entities having different structures as long as it is a valid JSON. For example, the following is another entity's representation:
{
"entity_id": "1",
"entity_name": "invoice",
"entity_json": {
"invoice_id": "1011",
"items": {
"item_id": "1",
"quantity": "3",
"price": "$100"
},
"date": "01-01-2020",
"customer": {
"id": "3",
"address": {
"street": "some_street",
"country": "CZ",
...
}
}
}
}
I want to be able to partially parse this JSON into an Entity POJO using Gson in Java. That is, I'll have an entity POJO like the one shown below:
public class Entity {
private String entity_id;
private String entity_name;
private String entity_json; // <-- entity_json is a String
// getters and setters
}
/*
* entity_json (for employee) = "{ \"employee_id\": \"1\", \"employee... }"
* entity_json (for invoice) = "{ \"invoice_id\": \"1011\", \"items... }"
*/
and I'm planning on performing any operation on entity_json using JsonPath.
Is there any way I can achieve this WITHOUT having to explicitly set entity_json in the JSON structure as a string with escapes?
Any help is appreciated here. Thanks!
You can avoid using a String for your entity_json by using Gson's JsonObject.
Here is my revised Entity class:
import com.google.gson.JsonObject;
public class MyEntity {
private String entity_id;
private String entity_name;
private JsonObject entity_json;
// getters and setters not shown
}
Then you can populate instances as follows:
MyEntity myEntityOne = new Gson().fromJson(JSON_ONE, MyEntity.class);
MyEntity myEntityTwo = new Gson().fromJson(JSON_TWO, MyEntity.class);
System.out.println(myEntityOne.getEntity_json());
System.out.println(myEntityTwo.getEntity_json());
In the above code, JSON_ONE and JSON_TWO are just strings containing the two sample JSONs from your question.
The console prints out the following (snipped for brevity):
{"employee_id":"e01","employee_name":"john","employee_phone_numbers":["1234567","8765433"]}
{"invoice_id":"1011","items":{"item_id":"1","quantity":"3","price":"$100"},"date":"01-01-2020"...
You can, of course, now use Gson to further manipulate each entity_json field as needed, since each one is itself a valid JSON object.

Is it possible to rename an #XmlPath annotated element while marshalling with MOXy to normalize the json representation?

I'm not sure if this is at all possible as it contradicts the semantics of #XmlPath itself, but if yes, please do help me with this.
I'm getting this json by calling some external API from my API implementation
{
"title": "Forrest Gump",
"writingCredits": {
"novel": "Winston Groom",
"screenplay": "Eric Roth"
},
"directedBy": "Robert Zemeckis",
"casts": ["Tom Hanks", "Rebecca Williams", "Sally Field"],
"releaseDate": "1994-06-07T00:00:00.000Z",
"producedBy": {
"producers": ["Wendy Finerman", "Steve Starkey"],
"co-producers": ["Charles Newrith"]
}
}
and mapping this to following POJO that'll be returned as resource from my own API
public class Film
{
private String title;
#XmlPath("writingCredits/screenplay/text()")
private String writer;
#XmlPath("directedBy/text()")
private String director;
#XmlPath("casts[0]/text()")
private String actor;
#XmlJavaTypeAdapter(DateUnmarshaller.class)
#XmlPath("releaseDate/text()")
private int releaseYear;
#XmlPath("producedBy/producers[0]/text()")
private String producer;
private String category;
//Commented getters and setters to save space
}
Here I'm able to map the necessary info to my POJO using MOXy but facing problem while marshalling the same.
While marshalling it retains the original nested structure of the received json though my POJO structure is not nested, I mean it is not referring to any other POJO.
Can I get something like this when I marshall my POJO to json:
{
"title": "Forrest Gump",
"writer": "Eric Roth",
"director": "Robert Zemeckis",
"actor": "Tom Hanks",
"releaseYear": 1994,
"producer": "Wendy Finerman"
}
but instead it showed up like this:
{
"title": "Forrest Gump",
"writingCredits": {
"screenplay": "Eric Roth"
},
"directedBy": "Robert Zemeckis",
"casts": "Tom Hanks",
"releaseDate": 1994,
"producedBy": {
"producers": "Wendy Finerman"
}
}
So, is there any way to deal with this?
And one more thing, for the category attribute I wanna decide its value if a particular json entry is present in received json, e.g. if the received json contains a json entry like
"animationInfo": {
"studio" : "pixar",
"some extra info" : [],
"and some more" : {}
}
then category should be set to "animation". Do I need to write one more XmlAdapter for it?
Thank you..!

Customized serialization of POJO to JSON in spring restTemplate

I am using the spring restTemplate to make POSTs to an endpoint and want it to convert my POJO to JSON. This is being done already. I have a list and it converts to JSONArray and does it successfully. I want to modify it a bit though where instead of it being an array, I want it to be a JSON with a key being the name of the list variable, and the value being the list.
Example is:
List<Record> records;
The above would create a JSON of
{
"records": [
{
"name": "test",
"address": "chicago"
},
{
"name": "stack",
"address": "overflow"
},
{
"name": "etc",
"address": "etc"
}
]
Rather than being [{},{},{}]
I think just simple create a DTO object which contains your List and return it. For instance:
public class SampleDTO{
private List<Record> records;
//getter setter
}
in the Controller, just return the ResponseEntity with the body is your SampleDTO
Hope this help.

json and Spring MVC

I have trouble with Spring MVC and json.
I use SimplecartJS to generate json data like this :
{"currency":"RUR",
"shipping":250,
"tax":0,
"taxRate":0,
"itemCount":2,
"item_name_1":"Name of product #1",
"item_quantity_1":6,
"item_price_1":159,
"item_options_1":"",
"item_name_2":"Name of product #2",
"item_quantity_2":2,
"item_price_2":159,
"item_options_2":"",
"form":{
"Fname":"UserName",
"Phone":"7123456789",
"Address":"UserAddress",
"Comment":"Comment Text"
}
}
My controller Spring
#RequestMapping(value = "/checkorder2", method = RequestMethod.POST, headers = "Accept=application/json")
public String test (#RequestBody OrderCon orderC)throws Exception{
ObjectMapper om = new ObjectMapper();
om.canSerialize(OrderCon.class);
System.out.println(om);
return test(orderC);
}
Code from client side
var url = 'http://localhost:8080/url'
jQuery.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
contentType:'application/json',
dataType: "json",
type: "POST",
url: url,
data: JSON.stringify(data),
And my question:
When I send data to controller, I have a mistake 400 Bad request. The request sent by the client was syntactically incorrect. When adding a new item field name will "item_name_2","item_name_3" etc. How I can parse this. I try parse to List, Set but it is not working. Please help.
UPD1: OrderCon.java
public class OrderCon {
private List<String> form;
private List<List<String>> json;
getters and setters...
}
There is no way you are going to be able to parse that data to a class like you have, since you need to add dynamic properties to a Java class.
You do however have two options to get the data out
First option is parse the json to a HasMap of Strings, ie. change your controller signature to
public String test (#RequestBody Map<String, String> orderC)
The other option is to use a JsonNode and deal with the data as a tree, here is an example http://wiki.fasterxml.com/JacksonTreeModel
I personally would try the latter first
You're getting 400 Bad Request because Spring is trying to map the passed JSON directly to your OrderCon class.
For this to work, the class would need to map to the keys specified in the JSON.
IE:
JSON:
{
"name" : "foo",
"phone": "111-111-1111"
}
would map to:
public class someJsonPojo(){
String name;
String phone;
//setters & getters
}
I don't think this will work well since instead of getting an array of items, you only get an item appended to the list as a new key:value. You should be able to modify the JSON so that you can map to an array of Item objects, which contain the name, quantity, price, etc.

Gson - Conditional JSON Deserialization (Sanity Checks)

I have code in my android project that correctly deserializes json into POJO's using gson. I wish to add some condtional acceptance checks (sanity checks) to the incoming json. For instance, with the data structure below, I wish for the gson parser to only add objects where the start date < end date. I know I could iterate through the list after it is populated to remove invalid items, but I was wondering if there was any way to reject the items on the fly. Any help would be appreciated.
Example JSON
{
"Items" : [
{
"Name" : "Example Name",
"Start" : "2010-10-16 10:00:00",
"End" : "2011-03-20 17:00:00",
<other fields>
},
<several more items>
]
}
ItemList.java
public class ItemList {
private List<ItemHeader> Items;
public void setItemHeaders(List<ItemHeader> headers) {
Items = headers;
}
public List<ItemHeader> getItemHeaders() {
return Items;
}
}
ItemHeader.java has fields for name, start, end and all the other fields.
You'd need to write your own deserializer and have it throw an exception when your condition isn't met.
http://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer
I don't know that you should do this, but it's possible.

Categories