Dynamically mapping JSON request to other JSON without POJO class - java

I want to create a functionality in code when I get JSON request and convert the fields of this JSON to another one JSON object based on fields mapping in DB.
For example:
Request Json
{
{
"param1": "value1",
"param2": "value2",
"data": {
"param3": "value3"
}
}
Table in DB:
param1 | newMappedParam1
param2 | newMappedParam2
param3 | newMappedParam3
New generated Json object:
{
{
"newMappedParam1": "value1",
"newMappedParam2": "value2",
"data": {
"newMappedParam3": "value3"
}
}
I can create POJO model object and then just to manipulate with this. But when the new parameter is added, I need also to update the POJO model and it requires to release a new version of application. This is not desired option.
I think on another approach like getting the JSON request , on the fly I convert to some JSONObject and then I map and build anew Json object. And when i'm required to add the new parameter , i just add the record in DB and no more new releases for this.
Do you think this approach is very good for this?
Thanks

Related

How to create a json file using existing json file as template?

I have a json file which is mostly standard for all my work, the only difference is few parameters.
Now I want to know how can I using java use this json file as a template and provide the parameters as input and save the new json file on local directory?
{
"key" : "HWM_NAME",
"value" : "PINE_SLS_SVC_CUST_CNTCT"
}, {
"key" : "TOPIC",
"value" : "SLS_SVC_CUST_CNTCT2"
}, {
"key" : "SRC_SCHEMA",
"value" : "party_pkg"
}, {
"key" : "SRC_TABLE",
"value" : "SLS_SVC_CUST_CNTCT"
}, {
"key" : "TGT_SCHEMA",
"value" : "mstrdata_hub"
}, {
"key" : "TGT_TABLE",
"value" : "SLS_SVC_CUST_CNTCT"
} ]
},
So here I wish to just change the Value: "PINE_SLS_SVC_CUST_CNTCT" to some other value that I would take as input from user and give me a new json file with those values.
PS: I am working on Java Swing to create a GUI to get the parameters from the user and provide the json file as output.enter image description here
this is how GUI looks
Consider using some JSON Library, for example GSon
Read the values from json
List<LinkedTreeMap> values = gson.fromJson(json, ArrayList.class);
...
update the values, here you can write values from UI components!!!!
for (LinkedTreeMap pair : values) {
//Update values
System.out.println(pair.toString());
}
And generate JSON from java objects
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
...
Gson gson = new Gson();
String json = gson.toJson(values);

Improving processing time for mapping one json object to another

I am working on a module where i am getting a JSON response from a RESTful web service. The response is something like below.
[{
"orderNumber": "test order",
"orderDate": "2016 - 01 - 25",
"Billing": {
"Name": "Ron",
"Address": {
"Address1": "",
"City": ""
}
},
"Shipping": {
"Name": "Ron",
"Address": {
"Address1": "",
"City": ""
}
}
}]
This is not the complete response, but only with important elements just to elaborate the issue.
So what i need to do is, convert this JSON response into another JSON that my application understands and can process. Say the below for example.
{
"order_number": "test order",
"order_date": "2016-01-25",
"bill_to_name": "Ron",
"bill_to_address": "",
"bill_to_city": "",
"ship_from_name": "Ron",
"ship_from_Address": "",
"ship_from_city": ""
}
The idea that i had tried was to convert the JSONObject in the response i receive to a hashmap using JACKSON and then use StrSubstitutor to replace the placeholders in my application json with proper values from response json(My Application string with placeholders Shown below).
{"order_number":"${orderNumber}","order_date":"${orderDate}","bill_to_name":"${Billing.name}","bill_to_address":"${Billing.Address}","bill_to_city":"${Billing.City}","ship_from_name":"${Shipping.Name}","ship_from_Address":"${Shipping.Address}","ship_from_city":"${Shipping.City}"}
But the issue i faced was that
JSON to MAP didn't work with nested JSONOBJECT as shown in the response above.
Also to substitute Billing.Name/Shipping.Name etc, even if i extract the Shipping/Billing JSONObjects from the response, when i
would convert them to hashmap, they would give me Name, City,
Address1 as keys and not Billing.Name, Billing.City etc.
So as a solution i wrote the below piece of code which takes the response JSONObject(srcObject) and JSONObject of my application(destObject) as inputs, performs processing and fits in the values from the response JSON into my application JSON.
public void mapJsonToJson(final JSONObject srcObject, final JSONObject destObject){
for(String key : destObject.keys()){
String srcKey = destObject.getString(key)
if(srcKey.indexOf(".") != -1){
String[] jsonKeys = srcKey.split("\\.")
if(srcObject.has(jsonKeys[0])){
JSONObject tempJson
for(int i=0;i<jsonKeys.length - 1;i++){
if(i==0) {
tempJson = srcObject.getJSONObject(jsonKeys[i])
} else{
tempJson = tempJson.getJSONObject(jsonKeys[i])
}
}
destObject.put(key, tempJson.getString(jsonKeys[jsonKeys.length - 1]))
}
}else if(srcObject.has(srcKey)){
String value = srcObject.getString(srcKey)
destObject.put(key, value)
}
}
}
The issue with this piece of code is that it takes some time to process. I want to know is there a way i can implement this logic in a better way with less processing time?
You should create POJOs for your two data types, and then use Jackson's mapper to deserialize the REST data in as the first POJO, and then have a copy constructor on your second POJO that accepts the POJO from the REST service, and copies all the data to its fields. Then you can use Jackson's mapper to serialize the data back into JSON.
Only if the above still gives you performance issues would I start looking at faster but more difficult algorithms such as working with JsonParser/JsonGenerator directly to stream data.
I feel the standard approach will be to use XSLT equivalent for JSON. JOLT seems to be one such implementation. Demo page can be found here. Have a look at it.

Issue with serializing single-element ArrayList to JSON

I am writing Junit test case for my REST service, i am setting the values(below is the piece of code) to get the payload required for REST service
Payload jsonPayload = new Payload ();
payload.setAcc("A");
List<Details> details= new ArrayList<Details>;
Details detail = new Details();
detail.setTotalAmount(1);
detail.setCurrency("dollar");
details.add(detail);
payload.getDetails().addAll(details);
I want JSON to be built in format mentioned below, but I am not getting the JSON as expected, details should be in form of Array.
Required JSON -
{
"Acc" : "A",
"details": [
{
"totalAmount":1,
"currency":"dollar"
}
]
}
Output JSON -
{
"Acc" : "A",
"details":
{
"totalAmount":1,
"currency":"dollar"
}
}
Can anyone help me how can I achieve this?

How to create JSON Schema for Name/Value structure?

My problem is that i am serializing the content of map to JSON.
In the output (JSON), i have object that follow key/name syntax rule.
The key is created from map key, and the name from the value.
Model Example:
class Storage {
Map<String,String> values = new HashMap<>();
{
map.put("key1","key1");
map.put("key2","key2");
map.put("key3","key3");
}
}
JSON Example object:
{
key1=value1,
key2=value2,
key3=value3
}
JSON Schema:
{
"name": "storage",
"description": "Store of key values",
"properties": {
// How can we describe the properties if we do not know the name ?
}
}
The issue is that i do not know what the values will be but i know that they will be some.
Can you help me to provide me the full definition of schema?
Disclaimer:
I know that this can be also serialized as
{
values: [
{key="key1", value="value1"},
{key="key2", value="value2"},
{key="key3", value="value3"}
]
}
but is do not want to have array in the JSON.
Assuming your validator supports it you can use patternProperties.
For the schema...
{
"title": "Map<String,String>",
"type": "object",
"patternProperties": {
".{1,}": { "type": "string" }
}
}
...and the document...
{
"foo":"bar",
"baz":1
}
...the value of property foo is valid because it is a string but baz fails validation because it is a number.
I used the Solution suggested by #augurar
"additionalProperties": { "type": "string" }
for AWS API Gateway Model .... and the SDK was able to generate the Map variable as required in Java / Android SDK
#Arne Burmeister - in my case - Solution 1 didnt worked as needed - although it didnt gave any error in the Model (Schema Created)

Jackson: Mapping dynamic JSON response

I'm retrieving data from a rest service and I'm using JSON to map the JSON response to java POJOs. All works fine, except the service will return a different JSON result for invalid calls, which is not mappable to the POJO:
{
"error":[
{
"code": 1,
"message":"Parameter is invalid."
}
]
}
UPDATE:
The response format for a valid call looks something like this:
persons: {
personCount: 14
person: [
{
firstname: "Michael"
name: "Bolton"
}
]
}
I'm mapping the response like this:
Person person = mapper.readValue(in, Person.class);
I've looked through the API and some SO and blog-postings, but I didn't find a hint on how to approach this so far. Can you give me a hint?

Categories