Merge (Concat) Multiple JSONObjects in Java - java

I am consuming some JSON from two different sources, I end up with two JSONObjects and I'd like to combine them into one.
Data:
"Object1": {
"Stringkey":"StringVal",
"ArrayKey": [Data0, Data1]
}
"Object2": {
"Stringkey":"StringVal",
"Stringkey":"StringVal",
"Stringkey":"StringVal",
}
Code, using http://json.org/java/ library:
// jso1 and jso2 are some JSONObjects already instantiated
JSONObject Obj1 = (JSONObject) jso.get("Object1");
JSONObject Obj2 = (JSONObject) jso.get("Object2");
So in this situation I'd like to combine Obj1 and Obj2, either to make a totally new JSONObject or concat one to the other. Any ideas besides pulling them all apart and individually adding in by puts?

If you want a new object with two keys, Object1 and Object2, you can do:
JSONObject Obj1 = (JSONObject) jso1.get("Object1");
JSONObject Obj2 = (JSONObject) jso2.get("Object2");
JSONObject combined = new JSONObject();
combined.put("Object1", Obj1);
combined.put("Object2", Obj2);
If you want to merge them, so e.g. a top level object has 5 keys (Stringkey1, ArrayKey, StringKey2, StringKey3, StringKey4), I think you have to do that manually:
JSONObject merged = new JSONObject(Obj1, JSONObject.getNames(Obj1));
for(String key : JSONObject.getNames(Obj2))
{
merged.put(key, Obj2.get(key));
}
This would be a lot easier if JSONObject implemented Map, and supported putAll.

In some cases you need a deep merge, i.e., merge the contents of fields with identical names (just like when copying folders in Windows). This function may be helpful:
/**
* Merge "source" into "target". If fields have equal name, merge them recursively.
* #return the merged object (target).
*/
public static JSONObject deepMerge(JSONObject source, JSONObject target) throws JSONException {
for (String key: JSONObject.getNames(source)) {
Object value = source.get(key);
if (!target.has(key)) {
// new value for "key":
target.put(key, value);
} else {
// existing value for "key" - recursively deep merge:
if (value instanceof JSONObject) {
JSONObject valueJson = (JSONObject)value;
deepMerge(valueJson, target.getJSONObject(key));
} else {
target.put(key, value);
}
}
}
return target;
}
/**
* demo program
*/
public static void main(String[] args) throws JSONException {
JSONObject a = new JSONObject("{offer: {issue1: value1}, accept: true}");
JSONObject b = new JSONObject("{offer: {issue2: value2}, reject: false}");
System.out.println(a+ " + " + b+" = "+JsonUtils.deepMerge(a,b));
// prints:
// {"accept":true,"offer":{"issue1":"value1"}} + {"reject":false,"offer":{"issue2":"value2"}} = {"reject":false,"accept":true,"offer":{"issue1":"value1","issue2":"value2"}}
}

You can create a new JSONObject like this:
JSONObject merged = new JSONObject();
JSONObject[] objs = new JSONObject[] { Obj1, Obj2 };
for (JSONObject obj : objs) {
Iterator it = obj.keys();
while (it.hasNext()) {
String key = (String)it.next();
merged.put(key, obj.get(key));
}
}
With this code, if you have any repeated keys between Obj1 and Obj2 the value in Obj2 will remain. If you want the values in Obj1 to be kept you should invert the order of the array in line 2.

This wrapper method will help :
private static JSONObject merge(JSONObject... jsonObjects) throws JSONException {
JSONObject jsonObject = new JSONObject();
for(JSONObject temp : jsonObjects){
Iterator<String> keys = temp.keys();
while(keys.hasNext()){
String key = keys.next();
jsonObject.put(key, temp.get(key));
}
}
return jsonObject;
}

Thanks to Erel. Here is a Gson version.
/**
* Merge "source" into "target". If fields have equal name, merge them recursively.
* Null values in source will remove the field from the target.
* Override target values with source values
* Keys not supplied in source will remain unchanged in target
*
* #return the merged object (target).
*/
public static JsonObject deepMerge(JsonObject source, JsonObject target) throws Exception {
for (Map.Entry<String,JsonElement> sourceEntry : source.entrySet()) {
String key = sourceEntry.getKey();
JsonElement value = sourceEntry.getValue();
if (!target.has(key)) {
//target does not have the same key, so perhaps it should be added to target
if (!value.isJsonNull()) //well, only add if the source value is not null
target.add(key, value);
} else {
if (!value.isJsonNull()) {
if (value.isJsonObject()) {
//source value is json object, start deep merge
deepMerge(value.getAsJsonObject(), target.get(key).getAsJsonObject());
} else {
target.add(key,value);
}
} else {
target.remove(key);
}
}
}
return target;
}
/**
* simple test
*/
public static void main(String[] args) throws Exception {
JsonParser parser = new JsonParser();
JsonObject a = null;
JsonObject b = null;
a = parser.parse("{offer: {issue1: null, issue2: null}, accept: true, reject: null}").getAsJsonObject();
b = parser.parse("{offer: {issue2: value2}, reject: false}").getAsJsonObject();
System.out.println(deepMerge(a,b));
// prints:
// {"offer":{},"accept":true}
a = parser.parse("{offer: {issue1: value1}, accept: true, reject: null}").getAsJsonObject();
b = parser.parse("{offer: {issue2: value2}, reject: false}").getAsJsonObject();
System.out.println(deepMerge(a,b));
// prints:
// {"offer":{"issue2":"value2","issue1":"value1"},"accept":true}
}

A ready method to merge any number of JSONObjects:
/**
* Merges given JSONObjects. Values for identical key names are merged
* if they are objects, otherwise replaced by the latest occurence.
*
* #param jsons JSONObjects to merge.
*
* #return Merged JSONObject.
*/
public static JSONObject merge(
JSONObject[] jsons) {
JSONObject merged = new JSONObject();
Object parameter;
for (JSONObject added : jsons) {
for (String key : toStringArrayList(added.names())) {
try {
parameter = added.get(key);
if (merged.has(key)) {
// Duplicate key found:
if (added.get(key) instanceof JSONObject) {
// Object - allowed to merge:
parameter =
merge(
new JSONObject[]{
(JSONObject) merged.get(key),
(JSONObject) added.get(key)});
}
}
// Add or update value on duplicate key:
merged.put(
key,
parameter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return merged;
}
/**
* Convert JSONArray to ArrayList<String>.
*
* #param jsonArray Source JSONArray.
*
* #return Target ArrayList<String>.
*/
public static ArrayList<String> toStringArrayList(JSONArray jsonArray) {
ArrayList<String> stringArray = new ArrayList<String>();
int arrayIndex;
for (
arrayIndex = 0;
arrayIndex < jsonArray.length();
arrayIndex++) {
try {
stringArray.add(
jsonArray.getString(arrayIndex));
} catch (JSONException e) {
e.printStackTrace();
}
}
return stringArray;
}

This is what I do
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* This class has all static functions to merge 2 objects into one
*/
public class MergeHelper {
private static ObjectMapper objectMapper = new ObjectMapper();
/**
* return a merge JsonNode, merge newJson into oldJson; override or insert
* fields from newJson into oldJson
*
* #param oldJson
* #param newJson
* #return
*/
public static JsonNode mergeJsonObject(JsonNode oldJson, JsonNode newJson) {
ObjectNode merged = objectMapper.createObjectNode();
merged.setAll((ObjectNode) oldJson);
merged.setAll((ObjectNode) newJson);
return merged;
}
}

For me that function worked:
private static JSONObject concatJSONS(JSONObject json, JSONObject obj) {
JSONObject result = new JSONObject();
for(Object key: json.keySet()) {
System.out.println("adding " + key + " to result json");
result.put(key, json.get(key));
}
for(Object key: obj.keySet()) {
System.out.println("adding " + key + " to result json");
result.put(key, obj.get(key));
}
return result;
}
(notice) - this implementation of concataion of json is for import
org.json.simple.JSONObject;

It's a while from the question but now JSONObject implements "toMap" method so you can try this way:
Map<String, Object> map = Obj1.toMap(); //making an HashMap from obj1
map.putAll(Obj2.toMap()); //moving all the stuff from obj2 to map
JSONObject combined = new JSONObject( map ); //new json from map

In addition to #erel's answer, I had to make this edit (I'm using org.json.simple) to the outer else for dealing with JSONArray's:
// existing value for "key" - recursively deep merge:
if (value instanceof JSONObject) {
JSONObject valueJson = (JSONObject)value;
deepMerge(valueJson, (JSONObject) target.get(key));
}
// insert each JSONArray's JSONObject in place
if (value instanceof JSONArray) {
((JSONArray) value).forEach(
jsonobj ->
((JSONArray) target.get(key)).add(jsonobj));
}
else {
target.put(key, value);
}

I used string to concatenate new object to an existing object.
private static void concatJSON() throws IOException, InterruptedException {
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader(new File(Main.class.getResource("/file/user.json").toURI())));
JSONObject jsonObj = (JSONObject) obj; //usernameJsonObj
String [] values = {"0.9" , Date.from(Calendar.getInstance().toInstant()).toLocaleString()},
innermost = {"Accomplished", "LatestDate"},
inner = {"Lesson1", "Lesson2", "Lesson3", "Lesson4"};
String in = "Jayvee Villa";
JSONObject jo1 = new JSONObject();
for (int i = 0; i < innermost.length; i++)
jo1.put(innermost[i], values[i]);
JSONObject jo2 = new JSONObject();
for (int i = 0; i < inner.length; i++)
jo2.put(inner[i], jo1);
JSONObject jo3 = new JSONObject();
jo3.put(in, jo2);
String merger = jsonObj.toString().substring(0, jsonObj.toString().length()-1) + "," +jo3.toString().substring(1);
System.out.println(merger);
FileWriter pr = new FileWriter(file);
pr.write(merger);
pr.flush();
pr.close();
}

Merging typed data structure trees is not trivial, you need to define the precedence, handle incompatible types, define how they will be casted and merged...
So in my opinion, you won't avoid
... pulling them all apart and individually adding in by puts`.
If your question is: Has someone done it for me yet?
Then I think you can have a look at this YAML merging library/tool I revived. (YAML is a superset of JSON), and the principles are applicable to both.
(However, this particular code returns YAML objects, not JSON. Feel free to extend the project and send a PR.)

Today, I was also struggling to merge JSON objects and came with following solution (uses Gson library).
private JsonObject mergeJsons(List<JsonObject> jsonObjs) {
JsonObject mergedJson = new JsonObject();
jsonObjs.forEach((JsonObject jsonObj) -> {
Set<Map.Entry<String, JsonElement>> entrySet = jsonObj.entrySet();
entrySet.forEach((next) -> {
mergedJson.add(next.getKey(), next.getValue());
});
});
return mergedJson;
}

Somebody already mentioned above. I'll just post a short version.
To merge two JSONObject json1 & json2 You could simply deal it with String like this:
String merged = json1.toString().substring(0, json1.length() - 1) + "," +
json2.toString().substring(1);
JSONObject mergedJson = new JSONObject(merged);
Of course, do not forget deal with JSONException. :)
Hope this could help you.

An improved version of merge on Gson's JsonObjects - can go any level of nested structure
/**
* Merge "source" into "target".
*
* <pre>
* An improved version of merge on Gson's JsonObjects - can go any level of nested structure:
* 1. merge root & nested attributes.
* 2. replace list of strings. For. eg.
* source -> "listOfStrings": ["A!"]
* dest -> "listOfStrings": ["A", "B"]
* merged -> "listOfStrings": ["A!", "B"]
* 3. can merge nested objects inside list. For. eg.
* source -> "listOfObjects": [{"key2": "B"}]
* dest -> "listOfObjects": [{"key1": "A"}]
* merged -> "listOfObjects": [{"key1": "A"}, {"key2": "B"}]
* </pre>
* #return the merged object (target).
*/
public static JsonObject deepMerge(JsonObject source, JsonObject target) {
for (String key: source.keySet()) {
JsonElement srcValue = source.get(key);
if (!target.has(key)) {
target.add(key, srcValue);
} else {
if (srcValue instanceof JsonArray) {
JsonArray srcArray = (JsonArray)srcValue;
JsonArray destArray = target.getAsJsonArray(key);
if (destArray == null || destArray.size() == 0) {
target.add(key, srcArray);
continue;
} else {
IntStream.range(0, srcArray.size()).forEach(index -> {
JsonElement srcElem = srcArray.get(index);
JsonElement destElem = null;
if (index < destArray.size()) {
destElem = destArray.get(index);
}
if (srcElem instanceof JsonObject) {
if (destElem == null) {
destElem = new JsonObject();
}
deepMerge((JsonObject) srcElem, (JsonObject) destElem);
} else {
destArray.set(index, srcElem);
}
});
}
} else if (srcValue instanceof JsonObject) {
JsonObject valueJson = (JsonObject)srcValue;
deepMerge(valueJson, target.getAsJsonObject(key));
} else {
target.add(key, srcValue);
}
}
}
return target;
}

Here is a version of https://stackoverflow.com/a/15070484/9897317 including JSONArrays :
/**
* Merge "source" into "target". If fields have equal name, merge them recursively.
* #return the merged object (target).
*/
public static JSONObject deepMerge(JSONObject source, JSONObject target) throws JSONException {
for (String key: JSONObject.getNames(source)) {
Object value = source.get(key);
if (value != null) {
if (!target.has(key)) {
// new value for "key":
target.put(key, value);
} else {
// existing value for "key" - recursively deep merge:
if (value instanceof JSONObject) {
JSONObject valueJson = (JSONObject)value;
deepMerge(valueJson, target.getJSONObject(key));
} else if (value instanceof JSONArray) {
JSONArray arr = (JSONArray) value;
JSONArray newArr = new JSONArray();
for (int i = 0; i < arr.length(); i++) {
newArr.put(deepMerge(arr.getJSONObject(i), target.getJSONArray(key).getJSONObject(i)));
}
target.put(key, newArr);
} else {
target.put(key, value);
}
}
}
}
return target;
}

Related

Create JSON object from List in Java

I have a List<String> where each element represents a node and a String which is the value that corresponds to the last node of that list. The list represents the path to the value. So, basically each element of the list is the value of the previous element. I would like to create a JSON object from it using Jackson. However, this needs to be done dynamically, not explicitly setting the nodes of the JSON object, because the list will not always be the same.
So, I am wondering if there is a way to convert or iterate through the list and create the JSON object.
So, if my list looks like this:
["user", "car", "brand"] and the value is "BMW", the JSON object should look like this:
{
"user":
{
"car":
{
"brand": "BMW"
}
}
}
Iterate through the list in reverse and upon each iteration create a new JsonNode for the list element, add the previous JsonNode as a child to the new JsonNode and overwrite the original reference with the new JsonNode. Rinse and repeat.
Something like...
final String value = "BMW"; // whatever the final "value" is.
final ObjectMapper objectMapper = new ObjectMapper();
ObjectNode json = null;
for (int i = list.size() - 1; i >= 0; i--) {
final String prop = list.get(i);
final ObjectNode objectNode = objectMapper.createObjectNode();
if (json == null) {
objectNode.put(prop, value);
} else {
objectNode.put(prop, json);
}
json = objectNode;
}
Here is the piece of code which you need
package uk.co.vishal;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Answer {
public static void main(String[] args) throws JsonProcessingException {
List<String> data = new ArrayList<>();
data.add("user");
data.add("car");
data.add("brand");
System.out.println(data.toString());
Map<String, String> mydata = new HashMap<>();
Map<String, JSONObject> newdata = new HashMap<>();
JSONObject result = new JSONObject();
boolean flag = true;
for (int i = data.size() - 1; i >= 0; i--) {
if (flag) {
mydata.put(data.get(i), "BMW");
result = generateJson(mydata);
flag = false;
} else {
newdata.put(data.get(i), result);
result = generateJson(newdata);
newdata.clear();
}
}
System.out.println(result);
/*
* Here is the output:
* {
"user": {
"car": {
"brand": "BMW"
}
}
}
*
* */
}
private static JSONObject generateJson(Map data) {
return new JSONObject(data);
}
}
I hope you will be sorted !!

Java: Append key value pair to nested json object

I am given three inputs .
A JSON object (nested)
A node structure
key value pair
My task is to append the key value pair to a node by looking at the node structure and updating the original JSON.
For example, if the inputs are,
JSON Object
{
a:
{
b:
{
c:{}
}
}
}
Node structure
a.b.
Key k and value v
The final updated JSON should look like
{
a:
{
b:
{
key:val
c:{}
}
}
}
Please note that the original JSON can be {} also. Then I have to build the whole JSON by looking at the node structure.
Here is my code
making a key value pair
public JSONObject makeEV(String ele, String val) throws JSONException{
JSONObject json =new JSONObject();
json.put(ele, val);
return json;
}
Appending it to JSON
public void modifiedJSON(JSONObject orgJson, String nodeStruct, JSONObject ev) throws JSONException{
JSONObject newJson = new JSONObject();
JSONObject copyJson = newJson;
char last = nodeStruct.charAt(nodeStruct.length()-1);
String lastNode = String.valueOf(last);
int i = 0;
while(orgJson.length() != 0 || i< nodeStruct.length()){
if(orgJson.length() ==0){
if(nodeStruct.charAt(i) == last){
newJson.put(String.valueOf(last), ev.toString());
}else{
newJson.put(String.valueOf(nodeStruct.charAt(i)), "");
}
newJson = newJson.getJSONObject(String.valueOf(nodeStruct.charAt(i)));
}
else if(i >= nodeStruct.length()){
if(orgJson.has(lastNode)){
newJson.put(String.valueOf(last), ev.toString());
}else{
}
}
}
}
I am stuck here. Please help. Thanks in advance.
It could be done using String#split(regex) as next:
public void modifiedJSON(JSONObject orgJson, String nodeStruct,
String targetKey, String value) {
// Split the keys using . as separator
String[] keys = nodeStruct.split("\\.");
// Used to navigate in the tree
// Initialized to the root object
JSONObject target = orgJson;
// Iterate over the list of keys from the first to the key before the last one
for (int i = 0; i < keys.length - 1; i++) {
String key = keys[i];
if (!target.has(key)) {
// The key doesn't exist yet so we create and add it automatically
target.put(key, new JSONObject());
}
// Get the JSONObject corresponding to the current key and use it
// as new target object
target = target.getJSONObject(key);
}
// Set the last key
target.put(targetKey, value);
}

How to store a JsonArray in a Map?

I have used the following Code
JSONArray jsonArray = new JSONArray(incomingData);
Map<String,String> map=new HashMap<String,String>();
for(int i=0;i<jsonArray.length();i++){
JSONObject j = jsonArray.getJSONObject(i);
Iterator<?> it = j.keys();
while (it.hasNext()) {
String n = it.next().toString();
map.put(n, j.getString(n));
}
}
But when I execute this code it's throwing an Exception.
org.json.JSONException: JSONObject["low_stock_date"] not a string.
JsonArray Used
[
{
"item_id": "1",
"product_id": "1",
"stock_id": "1",
"qty": "99.0000",
"low_stock_date": null
},
{
"item_id": "2",
"product_id": "2",
"stock_id": "1",
"qty": "100.0000",
"low_stock_date": null
}
]
Please help me to over come this issue.
The value of low_stock_date is null. thats why it is throwing this error.
Just add one check for null before adding it into Map.
if(!j.isNull(n)){
map.put(n, j.getString(n));
}
else{
map.put(n, null);
}
for(int i=0;i<jsonArray.length();i++){
JSONObject j = jsonArray.getJSONObject(i);
Iterator<?> it = j.keys();
while (it.hasNext()) {
String n = it.next().toString();
map.put(n, j.getString(n));
}
}
You are doing the above, inside for loop & storing the key/value pair in Map.
As same keys are there in every JSONObject so only values in last jsonobject would be there in for Map keys.
As an alternate you can create an ArrayList for storing these Maps, which you can get while converting each JSONObject to Map
One more thing you can do here is using a parser like Jackson Parser
HashMap<String,String> result =
new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);
(where JSON_SOURCE is a File, input stream, reader, or json content String).
That would be quick & better way of doing the what you want.
This is actually how the method is implemented:
/**
* Get the string associated with a key.
*
* #param key
* A key string.
* #return A string which is the value.
* #throws JSONException
* if there is no string value for the key.
*/
public String getString(String key) throws JSONException {
Object object = this.get(key);
if (object instanceof String) {
return (String) object;
}
throw new JSONException("JSONObject[" + quote(key) + "] not a string.");
}
You could check the type of the to-be-loaded object to see if it is null:
j.isNull(n);
and then act accordingly:
if (j.isNull(n)) {
// do something
} else {
// do something else
}

How to get dynamically changed Key's value in Json String using java

I'm trying to parse Json string using java, I have stuck up with some scenario.
See below is my JSON String:
"NetworkSettings": {
"Ports": {
"8080/tcp": [ // It will change dynamically like ("8125/udp" and "8080/udp" etc....)
{
"HostIp": "0.0.0.0",
"HostPort": "8080"
}
]
}
}
I try to parse the above json string by using the following code:
JsonObject NetworkSettings_obj=(JsonObject)obj.get("NetworkSettings");
if(NetworkSettings_obj.has("Ports"))
{
JsonObject ntw_Ports_obj=(JsonObject)NetworkSettings_obj.get("Ports");
if(ntw_Ports_obj.has("8080/tcp"))
{
JsonArray arr_ntwtcp=(JsonArray)ntw_Ports_obj.get("8080/tcp");
JsonObject ntwtcp_obj=arr_ntwtcp.get(0).getAsJsonObject();
if(ntwtcp_obj.has("HostIp"))
{
ntw_HostIp=ntwtcp_obj.get("HostIp").toString();
System.out.println("Network HostIp = "+ntw_HostIp);
}
if(ntwtcp_obj.has("HostPort"))
{
ntw_HostPort=ntwtcp_obj.get("HostPort").toString();
System.out.println("Network HostPort = "+ntw_HostPort);
}
}
else
{
ntw_HostIp="NA";
ntw_HostPort="NA";
}
}
else
{
ntw_HostIp="NA";
ntw_HostPort="NA";
}
In my code I have used this code
JsonArray arr_ntwtcp=(JsonArray)ntw_Ports_obj.get("8080/tcp");
to get the value of "8080/tcp"
How can I get the values of dynamically changing key like ("8125/udp","8134/udp", etc...)
Note: I'm using gson library for parsing
After modification
public static void main(String args[])
{
try
{
JsonParser parser = new JsonParser();
JsonObject obj=(JsonObject)parser.parse(new FileReader("sampleJson.txt"));
System.out.println("obj = "+obj);
JsonObject NetworkSettings_obj=(JsonObject)obj.get("NetworkSettings");
if(NetworkSettings_obj.has("Ports"))
{
JsonObject ntw_Ports_obj=(JsonObject)NetworkSettings_obj.get("Ports");
System.out.println("ntw_Ports_obj = "+ntw_Ports_obj);
Object keyObjects = new Gson().fromJson(ntw_Ports_obj, Object.class);
List keys = new ArrayList();
System.out.println(keyObjects instanceof Map); //**** here the statement prints false
if (keyObjects instanceof Map) // *** so controls doesn't enters into the if() condition block *** //
{
Map map = (Map) keyObjects;
System.out.println("Map = "+map);
keys.addAll(map.keySet());
String key = (String) keys.get(0);
JsonArray jArray = (JsonArray) ntw_Ports_obj.get(key);
System.out.println("Array List = "+jArray);
}
}
}
catch(Exception e)
{
}
}
You can do something like that (not tested but should be ok) :
if (ntw_Ports_obj.isJsonArray()) {
Iterator it = ntw_Ports_obj.getAsJsonArray().iterator();
while (it.hasNext()) {
JsonElement element = (JsonElement) it.next();
if(element.isJsonArray()){
JsonArray currentArray = element.getAsJsonArray();
// Do something with the new JsonArray...
}
}
}
So your problem is the key 8080/tcp is not fixed and it may change. when this situation you can try like this to get the value of the Dynamic key.
Set<Map.Entry<String, JsonElement>> entrySet = ntw_Ports_obj
.entrySet();
for (Map.Entry<String, JsonElement> entry : entrySet) {
String key = entry.getKey();
JsonArray jArray = (JsonArray) ntw_Ports_obj.get(key);
System.out.println(jArray);
}
Edit:
Object keyObjects = new Gson().fromJson(ntw_Ports_obj, Object.class);
List keys = new ArrayList();
/** for the given json there is a one json object within the 'Ports' so the 'keyObjects' will be the 'Map'**/
if (keyObjects instanceof Map) {
Map map = (Map) keyObjects;
keys.addAll(map.keySet());
/**
* keys is a List it may contain more than 1 value, but for the given
* json it will contain only one value
**/
String key = (String) keys.get(0);
JsonArray jArray = (JsonArray) ntw_Ports_obj.get(key);
System.out.println(jArray);
}

How to sort GSON Array based on a key?

Consider the following is my Array
[
{"id":10,"name":"name10","valid":true},
{"id":12,"name":"name12","valid":false},
{"id":11,"name":"name11","valid":false},
{"id":9,"name":"name9","valid":true}
]
Created a JsonArray out of it, like following code does:
//Create a JSON Parser using GSON library
objJsonParser = new JsonParser();
String strArrayText = [{"id":9,"name":"name9","valid":true}, ...]
JsonArray jsonArrayOfJsonObjects = objJsonParser.parse(strArrayText).getAsJsonArray();
Now, I am trying to sort jsonArrayOfJsonObjects based on name field.
Desired Output:
[
{"id":9,"name":"name9","valid":true},
{"id":10,"name":"name10","valid":false},
{"id":11,"name":"name11","valid":false},
{"id":12,"name":"name12","valid":true}
]
Could anyone help to sort this out with best apporach with respect to Java & Gson?
Your inputs are greatly appreciated.
First of all, the proper way to parse your JSON is to create a class to encapsulate your data, such as:
public class MyClass {
private Integer id;
private String name;
private Boolean valid;
//getters & setters
}
And then:
Type listType = new TypeToken<List<MyClass>>() {}.getType();
List<MyClass> myList = new Gson().fromJson(strArrayText, listType);
Now you have a List and you want to sort it by the value of the attribute id, so you can use Collections as explained here:
public class MyComparator implements Comparator<MyClass> {
#Override
public int compare(MyClass o1, MyClass o2) {
return o1.getId().compareTo(o2.getId());
}
}
And finally:
Collections.sort(myList, new MyComparator());
Try this library method as a simple JSON-level alternative to model classes creation:
/**
* Sort JSON-array by a given key name (numbers or text expected).
*
* #param jsonArray JSON-array to sort.
* #param keyNameToSort Key name to sort by. Expected are integer type
* (sorted ascending) or string type (sorted
* alphabetically).
*/
public static JsonArray
sortJsonArrayByKey(
JsonArray jsonArray,
String keyNameToSort) {
JsonArray sortedJsonArray = new JsonArray();
JsonObject jsonObject = null;
int jsonElementIndex;
TreeMap<Integer, JsonObject> integerSortedObjects = new TreeMap<>();
TreeMap<String, JsonObject> stringSortedObjects = new TreeMap<>();
for (
jsonElementIndex = 0;
jsonElementIndex < jsonArray.size();
jsonElementIndex++) {
try {
// A JSON-Object from JSON-array:
jsonObject =
jsonArray
.get(
jsonElementIndex)
.getAsJsonObject();
} catch (Exception notAnObject) {
}
for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
// Look for the given key in the JSON-object:
if (
entry.getKey()
.equals(keyNameToSort)) {
try {
// If key is of integer type:
integerSortedObjects.put(
entry
.getValue()
.getAsInt(),
jsonObject);
} catch (Exception notAnInt) {
try {
// If key is of string type:
stringSortedObjects.put(
entry
.getValue()
.getAsString(),
jsonObject);
} catch (Exception neitherIntNorString) {
}
}
}
}
}
// Add sorted by number values first:
for (Integer key : integerSortedObjects.keySet()) {
sortedJsonArray.add(
integerSortedObjects.get(
key));
}
// Add sorted by string values second:
for (String key : stringSortedObjects.keySet()) {
sortedJsonArray.add(
stringSortedObjects.get(
key));
}
return sortedJsonArray;
}
you can use Gson library https://sites.google.com/site/gson/gson-user-guide
to get the Array(the class should implement comparable) and sort with arrays.sort();
Thanks

Categories