Lets say I have two arrays of JSONObjects in memory and each object has a key that is similar in both arrays:
Array 1
[
{
"name": "Big Melons Co.",
"location": "Inner City Dubai"
"id": "1A"
},
{
"name": "Pear Flavored Juices Ltd",
"location": "Seychelles"
"id": "2A"
},
{
"name": "Squeeze My Lemons LLC",
"location": "UK"
"id": "3A"
}, {other JSON Objects...} ]
Array 2
[
{
"acceptsCard": "true"
"id": "1A"
},
{
"acceptsCard": "false"
"id": "2A"
},
{
"acceptsCard": "false"
"id": "3A"
}, {other JSON Objects...} ]
Now, I want to merge the two arrays together based on the primary key of "id" so they become one on my server side and then send the results back to my frontend - the resulting arraylist of objects should look like this:
MERGED ARRAY (Result)
[
{
"name": "Great Juice Co.",
"location": "Inner City Dubai"
"acceptsCard": "true"
"id": "1A"
},
{
"name": "Pear Flavored Juices Ltd",
"location": "Seychelles"
"acceptsCard": "false"
"id": "2A"
},
{
"name": "Squeeze My Lemons LLC",
"location": "UK"
"acceptsCard": "false"
"id": "3A"
}, {other JSON Objects...} ]
How can I do this efficiently?
I can think of one highly inefficient way to do this (I'm dreading implementing this) - I would loop though each item in either array 1 or 2 and use the equal() method for the string in the "id" field to see whether the two matches. If they match, I would create a new JSONObject to contain both the fields from array 1 and 2.
My Java is a little rusty but I would use a map.
List<JSONObject> objectsA = ... ;
List<JSONObject> objectsB = ... ;
Map entries = new HashMap<String, JSONObject>();
List<JSONObject> allObjects = new ArrayList<JSONObject>();
allObjects.addAll(objectsA);
allObjects.addAll(objectsB);
for (JSONObject obj: allObjects) {
String key = obj.getString("id");
JSONObject existing = entries.get(key);
if (existing == null) {
existing = new JSONObject();
entries.put(key, existing);
}
for (String subKey : obj.keys()) {
existing.put(subKey, obj.get(subKey));
}
}
List<JSONObject> merged = entries.values();
This is more efficient than two nested loops and there's still room for improvement.
EDIT: References to external documentation and related answers.
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
http://www.json.org/javadoc/org/json/JSONObject.html
https://stackoverflow.com/a/2403427/937006
Related
I have two JSON strings which are essentially arrays of JSONObject. The two JSON strings have below structure and keys:
JSON-1:
[
{
"title": "ABC",
"edition": 7,
"year": 2011
},
{
"title": "DEF",
"edition": 2,
"year": 2012
},
{
"title": "XYZ",
"edition": 3,
"year": 2013
}
]
And, JSON-2:
[
{
"title": "ABC",
"price": "20"
},
{
"title": "DEF",
"price": "20"
},
{
"title": "XYZ",
"price": "20"
}
]
Both these JSONs have a common key "title" based on which I want to merge these two JSONs, either merging JSON-2 values into JSON-1 or creating a JSON object with the merged result.
The merged result should look like below:
[
{
"title": "ABC",
"edition": 7,
"year": 2011,
"price": "20"
},
{
"title": "DEF",
"edition": 2,
"year": 2012
"price": "20"
},
{
"title": "XYZ",
"edition": 3,
"year": 2013
"price": "20"
}
]
How can I achieve this by minimum looping and minimum object creation? I also can not use entity/model classes. The idea is to do it without creating any model classes.
Note: I cannot use Gson because I don't have the approval to use the same.
I tried to use List<JSONObject> listObj = objectMapper.readValue(jsonOneString, new TypeReference<List<JSONObject>>(){});,
but I am getting an unknown property exception.
I tried JsonNode node = objectMapper.readTree(jsonOneString);, but I cannot proceed much further with this approach.
I know what I am doing here is highly inefficient, so looking for ways which will use no entity class, minimum new object creation and minimum loops. Kindly advise.
UPDATE: I updated the below code with a slight modification:
if (json1elem.get("title")!=null
&& json2elem.get("title")!=null
&& json1elem.get("title").equals(json2elem.get("title"))) {
//
}
JsonNode json1 = objectMapper.readTree(jsonOneString);
JsonNode json2 = objectMapper.readTree(jsonTwoString);
for (JsonNode json1elem : json1) {
for (JsonNode json2elem : json2) {
if (json1elem.get("title").equals(json2elem.get("title"))) {
((ObjectNode) json1elem).setAll((ObjectNode) json2elem);
break;
}
}
}
System.out.println(json1.toPrettyString());
Starting from the similar question,
Nested JSON Array in Java
I have a somewhat odd json as a response from a REST api(POST) call. I need to find out the id and name of the sub_items array in each items array element.
I tried like given below for which I am getting error like
org.json.JSONException: JSONObject["items.sub_items"] not found.
I also tried just 'sub_items' as the parameter also, but no. I am using GSON. No choice use others.
final JSONObject jsonObj = new JSONObject(JSON_STRING);
final JSONArray subItems = jsonObj.getJSONArray("items.sub_items");
final int n = subItems.length();
for (int i = 0; i < n; ++i) {
final JSONObject subI= subItems.getJSONObject(i);
System.out.println("id="+subI.getString("id"));
System.out.println("name="+subI.getString("name"));
}
The following is my json as a response from a REST api call.
{
"menu": {
"items": [{
"id": 1,
"code": "hot1_sub1_mnu",
"name": "Mutton",
"status": "1",
"sub_items": [{
"id": "01",
"name": "Mutton Pepper Fry",
"price": "100"
}, {
"id": "02",
"name": "Mutton Curry",
"price": "100"
}]
},
{
"id": "2",
"code": "hot1_sub2_mnu",
"name": "Sea Food",
"status": "1",
"sub_items": [{
"id": "01",
"name": "Fish Fry",
"price": "150"
}]
},
{
"id": "3",
"code": "hot1_sub3_mnu",
"name": "Noodles",
"status": "1",
"sub_items": [{
"id": "01",
"name": "Chicken Noodles",
"price": "70"
}, {
"id": "02",
"name": "Egg Noodles",
"price": "60"
}]
}
]
}}
As I said, my JSON is a response from an REST api call, and it is 7300 lines long, like shown below with the outline, as shown in code beautifier.
object {3}
infoTransferReqResp {1}
paramExtens : null
pageGroups {1}
pageGroups [1]
0 {4}
page_group_name : LFG - LG - Insured Summary
page_group_id : 8100
**pages [3]**
repeatingBlocks {1}
I needed to extract a string value 'questionText' from inside 'Pages' array. I used jsonPath() method with navigation path as given below which solved the problem.
JsonPath jsonPathEvaluator = response.jsonPath();
List<List<List<String>>> questions = jsonPathEvaluator.getList("pageGroups.pageGroups.pages.questions.questionText");
It gave me 3 ArrayLists one embedded in another corresponding to 3 arrays of 'pages'
I am trying to call an API using Retrofit in android. For this API I need the input parameter JSON object in proper sequence.
Only if I have the json in required sequence I get successful response from the API, otherwise it gives an error. To handle this issue I got one solution that is to first create a LinkedHashMap of input parameter then create the JSON of that LinkedHashMap. This way I'm acheaving the response from api.
but right now im confused how to create linkedHash map for below json
{
"RequestXml": {
"Authenticate": {
"InterfaceCode": "1",
"InterfaceAuthKey": "AirticketOnlineWebSite",
"AgentCode": "MOS0000001",
"Password": "KGBW5P"
},
"BookTicketRequest": {
"TrackNo": "0$182967|4|1AO",
"MobileNo": "9099776464",
"AltMobileNo": "9898989898",
"Email": "abc#gmail.com",
"Address": "Test",
"ClientRequestID": "",
"Passengers": {
"Passenger": [
{
"PaxSeqNo": "1",
"Title": "Mr",
"FirstName": "Savan",
"LastName": "Test",
"PassengerType": "A",
"DateOfBirth": "01/12/1992",
"PassportNo": "RTTTTGGBGB56356",
"PassportExpDate": "01/12/2024",
"PassportIssuingCountry": "IND",
"NationalityCountry": "IND"
}
]
},
"Segments": {
"Segment": [
{
"TrackNo":"0$182967|4|1AO",
"SegmentSeqNo": "1",
"AirlineCode": "UK",
"FlightNo": "888",
"FromAirportCode": "BOM",
"ToAirportCode": "DEL",
"DepDate": "30/09/2019",
"DepTime": "14:00",
"ArrDate": "30/09/2019",
"ArrTime": "16:00",
"FlightClass": "E",
"MainClass": "Y"
}
]
},
"AdditionalServices": {
},
"TotalAmount": "4735",
"MerchantCode": "PAY9zJhspxq7m",
"MerchantKey": "eSpbcYMkPoZYFPcE8FnZ",
"SaltKey": "WHJIIcNjVXaZj03TnDme",
"IsTicketing": "Yes"
}
}
}
how to calculate total value for the below JSON value U.O.M Wise in Java?
sequence can be vary. We cannot expect number of uoms and sequence of results.
i have created hashset and made unique uom.
{
value=100
uom=kg
},
{
value=200
uom=kg
},
{
value=100
uom=lt
},
{
value=100
uom=ab
},
{
value=100
uom=lt
}
Please provide some code ref
This is not valid JSON as it uses = as key\value separator (change to something like this and use tools like JSONLint to validate):
[{
"value": "100",
"uom": "kg"
}, {
"value": "200",
"uom": "kg"
}, {
"value": "100",
"uom": "lt"
}, {
"value": "100",
"uom": "ab"
}, {
"value": "100",
"uom": "lt"
}
]
Even having this structure you can parse it into a collection of touples (value, uom) and then just sum everything having same uom
For example you can use this:
javax.json.JsonArray body = Json.createReader(new StringReader(YOUR_JSON_STRING)).readArray();
and read a JSON to array of touples
The goal is to start with a JSON string, parse it, and then recursively process every object property or array element. If the value is an array, and every element of the array is an object that contains a "Name" property, sort the array by the object.Name. The recursion is important, because the real-world JSON I am going to have to apply this to has three levels of nested arrays that need to be sorted.
Once the arrays are sorted into a deterministic order, finally, it should re-serialize the whole thing with properties in alphabetical order.
The purpose of this is to ensure consistency of the JSON, so I can do string comparison between the expected and the actual, and have it not be thrown off if things are serialized in a different order, or the array elements come back in a non-deterministic order (which is currently the case).
In pseudo-code, it would look something like this:
process_array( arr ) {
if ( arr.every( e => e.has("Name") ) ) {
arr.sort( byName )
}
arr.forEach( process )
}
process_object( obj ) {
for each key in obj {
process( obj[key] )
}
process( it ) {
if ( isArray( it ) {
process_arr( it )
} else {
process_object( it )
}
}
standardize( json ) {
generic_obj = parse( json )
process( generic_obj )
return serialize_with_sorted_keys( generic_obj )
}
To make it concrete, given this input:
[
{
"Id": "1",
"Name": "foo",
"Children": [
{
"Name": "two",
"Value": 2
},
{
"Value": 1,
"Name": "one"
}
],
"Other": [ 1, 3, 2 ]
},
{
"Name": "bar",
"Id": "2",
"Children": [
{
"Name": "Banana",
"Value": 3
},
{
"Value": 4,
"Name": "Cherry"
},
{
"Apples": "are tasty",
"Name": "Apple",
"Value": 5
}
]
}
]
The expected output would be:
[ // array elements are sorted by .Name
{ // object properties are sorted by key
"Children": [ // sorted by .Name
{
"Apples": "are tasty",
"Name": "Apple",
"Value": 5
},
{
"Name": "Banana",
"Value": 3
},
{ // properties sorted by name
"Name": "Cherry",
"Value": 4
}
],
"Id": "2",
"Name": "bar"
},
{
"Children": [
{
"Name": "two",
"Value": 2
},
{
"Name": "one",
"Value": 1
}
],
"Id": "1",
"Name": "foo",
"Other": [ 1, 2, 3 ] // NOTE: order has been changed!
}
]
How do I do this in Java in a generic way?