I am given a JSON that will come in this format:
"template":{
"mod1":[
{
"param1":"55",
"param2":"5",
"param3":"somedata"
}
],
"mod2":[
{
"param1":"somedata",
"param2":"somedata"
}
],
"mod3":[
{
"param1":"somedata",
"param2":"somedata",
"param3":"somedata"
}
],
"mod4":[
{
"param1":"somedata",
"param2":"somedata"
}
],
"mod5":[
{
"param1":"somedata"
}
]
}
}
What is the easiest way to parse it? What I'd like is to get the params inside the mod and their associated values together, to store into a database. The way I am doing it is as so:
JSONObject obj = new JSONObject(json);
System.out.println(obj);
Iterator<String> keys = obj.keys();
while(keys.hasNext()) {
String key = keys.next();
JSONObject currTemplate = (JSONObject) obj.get(key);
if(currTemplate instanceof JSONObject) {
System.out.println("LIST OF ALL MODULES : " + currTemplate);
Iterator<String> currObjKeys = ((JSONObject) currTemplate).keys();
while(currObjKeys.hasNext()) {
String currObjKey = currObjKeys.next();
System.out.println("MODULE: " + currObjKey);
JSONArray array = currTemplate.getJSONArray(currObjKey);
System.out.println("ARRAY: " + array);
for(int i = 0; i < array.length(); i++){
JSONObject object = array.getJSONObject(i);
String[] names = JSONObject.getNames(object);
for(String name: names) {
System.out.println("PARAMS");
System.out.println(name);
System.out.println(object.get(name));
}
}
}
}
And it currently prints what I need correctly. What I am asking is if there is a more efficient way to do it - the way I currently have it is O(N^4), and I was wondering if anyone had any idea to parse the JSON in a more efficient way. Note: the params will not always be in form param1, param2, the names will always be different. Just changed it for confidentiality sake.
Thank you in advance.
Related
I am struggling with a specific problem, that I cannot think of correctly. The following is the problem
I have a map with key value like the following, i just used strings here
String key = "activate.message.success"
String value = "success"
String key1 = "activate.title"
String value1 = "Good Title"
String key2 = "activate.message.error"
String value2 = "error"
String key3 = "activate.message.short.poll"
String value3 = "This is short poll"
I need to build a json like the following
{
"activate":{
"message":{
"success":"success",
"error":"error",
"short":{
"poll":"This is short poll"
}
},
"title":"Good Title"
}
}
I could not think of a proper solution for this use case and struggling for 3 hours. I thought of using recursion, but i dont how exactly i could do. Please help with this. I am using java for this, I should use generic JSONObject to solve as there is not POJO mappings. So far I have just splitted the strings using separtor and stored in an another map like the following
public Map<String, Object> getJsonObjectFromKeyValueMap(Map<String, String> stringValueMap,
Map<String, Object> stringObjectMap) {
for (Entry entry : stringValueMap.entrySet()) {
String[] keyValueArrayString = entry.getKey().toString().split("\\.");
int sizeOfMap = keyValueArrayString.length;
int i = 0;
String concatString = "";
for (String processKey : keyValueArrayString) {
if (i < sizeOfMap - 1) {
concatString += processKey + ".";
stringObjectMap.put(concatString, (Object) new JSONObject());
} else {
concatString += processKey;
stringObjectMap.put(concatString, entry.getValue());
concatString = "";
}
i++;
}
}
return stringObjectMap;
}
First, let's update your data into a proper map :
Map<String, String> data = new HashMap<>();
data.put("activate.message.success", "success");
data.put("activate.title", "Good Title");
data.put("activate.message.error", "error");
data.put("activate.message.short.poll", "This is short poll");
Then, your logic is pretty close, for each node but the last, you create a new JSONObject, for the last, you insert the value.
If you try to build a JSONObject instead of the map directly, you would get a pretty good result already, well somewhat of a result.
The following will iterate a Map<String, String> of data.
For each entry, we split the key to getting the nodes.
Then, we just need to move in the json, if a node doesn't exist, we create it.
Then, for the last value, create the value.
public static JSONObject build(Map<String, String> data) {
JSONObject json = new JSONObject();
//Iterate the map entries
for (Entry<String, String> e : data.entrySet()) {
String[] keys = e.getKey().split("\\.");
// start from the root
JSONObject current = json;
for (int i = 0; i < keys.length; ++i) {
String key = keys[i];
//Search for the current node
try {
//If it exist, do nothing
current = current.getJSONObject(key);
} //If it does not exist
catch (JSONException ex) {
//Is it the last node, create the value
if (i == keys.length - 1) {
current.put(key, e.getValue());
} //Not the last node, create a new JSONObject
else {
JSONObject tmp = new JSONObject();
current.put(key, tmp);
current = tmp; //Always replace current with the last node to go deeped each iteration
}
}
}
}
return json;
}
And the example :
public static void main(String[] args) {
Map<String, String> data = new HashMap<>();
data.put("activate.message.success", "success");
data.put("activate.title", "Good Title");
data.put("activate.message.error", "error");
data.put("activate.message.short.poll", "This is short poll");
JSONObject json = build(data);
System.out.println(json.toString(4));
}
Ouptut:
{"activate": {
"message": {
"success": "success",
"short": {"poll": "This is short poll"},
"error": "error"
},
"title": "Good Title"
}}
Note : I used an exception to check for the existance of the key, if the map is huge, this could have some impact so you can simply use :
if(current.isNull(key)){
if (i == keys.length - 1) {
current.put(key, e.getValue());
} else {
JSONObject tmp = new JSONObject();
current.put(key, tmp);
current = tmp;
}
} else {
current = current.getJSONObject(key);
}
This was created using org.json/json
I have a list of objects and am converting into JSONArray. Am iterating over the JSONObjects and making an array of JSONObjects.
Now, i want to avoid duplicates objects to get insert into the JSONArray.
Please find my java code below.
JSONArray responseArray1 = new JSONArray();
if (!itemList.isEmpty())
{
jsonArray = new JSONArray(itemList);
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObj = jsonArray.getJSONObject(i);
JSONObject responseObj = new JSONObject();
String attr_label = jsonObj.optString("attr_label");
if(StringUtils.equalsIgnoreCase(attr_label, "long_description")) {
long_description = jsonObj.optString("value");
}
else if(StringUtils.equalsIgnoreCase(attr_label, "description")) {
description = jsonObj.optString("value");
}
responseObj.put("id", jsonObj.opt("id")); // i will get duplicate id
responseObj.put("code", jsonObj.opt("code")); // i will get duplicate code
responseObj.put("long_description", long_description);
responseObj.put("description", description);
responseArray1.put(responseObj);
}
}
Please find my actual jsonArray :
[
{
"code":"xyaz",
"attr_label":"long_description",
"id":"12717",
"value":"Command Module"
},
{
"code":"xyaz",
"attr_label":"description",
"id":"12717",
"value":"Set Point Adjustment"
},
]
Am expecting like the below jsonArray :
[
{
"code":"xyaz",
"id":"12717",
"long_description":"Command Module"
"description" : "Set Point Adjustment"
}
]
Update :
I have tried with the below code to avoid duplicate insertion of id & code field. but is not working properly. Its inserting duplicates also.
List<String> dummyList=new ArrayList<String>();
JSONArray responseArray2 = new JSONArray(itemList);
if (!itemList.isEmpty())
{
jsonArray = new JSONArray(itemList);
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObj = jsonArray.getJSONObject(i);
JSONObject responseObj = new JSONObject();
String itemCode = jsonObj.optString("code");
String id = jsonObj.optString("id");
if(!dummyList.contains(itemCode) && !dummyList.contains(id) ) {
dummyList.add(String.valueOf(jsonObj.opt("id")));
dummyList.add(String.valueOf(jsonObj.opt("code")));
responseObj.put("id", jsonObj.opt("id"));
responseObj.put("code", jsonObj.opt("code"));
responseObj.put("long_description", long_description);
responseObj.put("description", description);
responseArray2.put(responseObj);
}
}
}
Make a temporary array list and add unique code in that arrayList and check if it already exists in arrayList then don't put this again
String code = jsonObj.opt("code");
if(!arrayList.contains(code))
{
arrayList.add(code);
responseObj.put("id", jsonObj.opt("id"));
responseObj.put("code", jsonObj.opt("code"));
responseObj.put("long_description", long_description);
responseObj.put("description", description);
}
use TreeSet and add Comparator to their constructor in which it compare the duplicate data of the object.
for example:-
Set<Sample> sampleSet=new TreeSet<>(new Sample());
where Sample Class look like:-
class Sample implements Camparator<Sample>{
private String name;
private String id;
//getter
//setter
#Override
public String compare(Sample o1,Sample o2){
return o1.getName.compareTo(o2.getName);
}
}
This will give a set of unique name entries.
I have following JSONObject (not array, which I don't mind to convert). I am trying to do two things:
get the count of genre entry as "poetry" (count = 2).
get the key value of author name and genre:
authorName = malcolm
genreName = newsarticle
authorName = keats
genreName = poetry
{ "AddressBook" :{
"Details" :{
"authorname" :{
"Author-malcolm":{
"genre" :"poetry"
}
"Author-keats":{
"genre" :"poetry"
}
}
}
}
}
Code which I tried:
public static void main(String[] args) throws Exception, IOException, ParseException {
JSONParser parser = new JSONParser();
Object obj = parser.parse(new FileReader("My path to JSON"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray arrayhere = new JSONArray();
arrayhere.add(obj);
System.out.println(arrayhere);
int count = 0;
for(int i = 0; i < arrayhere.size(); i++) {
JSONObject element = arrayhere.getJSONObject(i);//The method getJSONObject(int) is undefined for the type JSONArray
String branchName = element.getString("genre");//The method getString(String) is undefined for the type JSONObject
if(branchName.equals("poetry")) {
count ++;
}
}
System.out.println("Count f0r poetry genre=" + count);
}
}
I have looked at solutions all over. There is no question similar to this at stackoverflow. I am not sure if the procedure is correct.
A few problems here.
First, I'm not sure where you got that example JSON but you can't work with that. That's not even valid JSON Formatting.
Looks like you want something like this:
{
AddressBook:
[
{
authorname: "author-malcom",
genre:"poetry"
},
{
authorname: "author-keats",
genre: "poetry"
}
]
}
That's the structure you're trying to create in JSON.
So, you're parsing this in from a file into a JSONObject that has a key called AddressBook inside of it. That key points to an array of JSONObjects representing authors. Each of those objects will have a key called genre. You're trying to access the genre key and count on a condition.
What you did above was create attempt to create a JSONObject from an invalid string, and then add the entire JSONObject itself into the JSONArray. JSONArray.add() doesn't convert an object to an array, it literally adds it onto the array.
jsonObj => {"Name":"name1","Id":1000}
jsonArray.add(jsonObj)
jsonArray => [{"Name":"name1","Id":1000}]
That's what you did in your code above. You didn't create an array from a JSONObject, you added an object to the array.
Proper use is going to look like:
Object obj = parser.parse(new FileReader("path_to_file"));
JSONObject jobj = (JSONObject) obj;
//access key AddressBook
JSONArray author_array = jobj.getJSONArray("AddressBook");
int poetry = 0;
for(int i = 0; i < author_array.length(); i++) {
JSONObject author = (JSONObject) author_array.get(i);
if(author.getString("genre").equals("poetry")) {
poetry++;
}
}
To summarize, you're problems come from a lack of understanding about JSON Formatting and how to access elements within a JSON Object.
Paste in the sample JSONObject I gave you above here. That site will let you visualize what you're working with.
JSONArray arr =
[
{"key1":"value1"},
{"key2":"value2"},
{"key3":"value3"},
{"key4":"value4"}
]
arr.get("key1") throws error. How can I get the value by key in JSONArray?
arr.getString("key1") also throws error. Should I loop through the array? Is it the only way to do it?
What is the error?
In Eclipse Debug perspective, these expressions returns as; error(s)_during_the_evaluation
You can parse your jsonResponse like below code :
private void parseJsonData(String jsonResponse){
try
{
JSONArray jsonArray = new JSONArray(jsonResponse);
for(int i=0;i<jsonArray.length();i++)
{
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
String value1 = jsonObject1.optString("key1");
String value2 = jsonObject1.optString("key2");
String value3 = jsonObject1.optString("key3");
String value4 = jsonObject1.optString("key4");
}
}
catch (JSONException e)
{
e.printStackTrace();
}
}
Sounds like you want to find a specific key from an array of JSONObjects. Problem is, it's an array, so you have to iterate over each element. One solution, assuming no repeat keys is...
private Object getKey(JSONArray array, String key)
{
Object value = null;
for (int i = 0; i < array.length(); i++)
{
JSONObject item = array.getJSONObject(i);
if (item.keySet().contains(key))
{
value = item.get(key);
break;
}
}
return value;
}
Now, let's say you want to find the value of "key1" in the array. You can get the value using the line: String value = (String) getKey(array, "key1"). We cast to a string because we know "key1" refers to a string object.
for (int i = 0; i < arr.length(); ++i) {
JSONObject jsn = arr.getJSONObject(i);
String keyVal = jsn.getString("key1");
}
You need to iterate through the array to get each JSONObject. Once you have the object of json you can get values by using keys
You can easy get a JSON array element by key like this:
var value = ArrName['key_1']; //<- ArrName is the name of your array
console.log(value);
Alternatively you can do this too:
var value = ArrName.key_1;
That's it!
I am new to parsing JSON in java. I have this JSON string:
[
{
"projectId":5,
"userName":"clinician",
"projectName":"r",
"projectSummary":"r",
"projectLanguage":"r",
"contactPersonName":"r",
"contactPersonCV":"r",
"contactPersonEmail":"r",
"contactPersonPhone":"r"
},
[
{
"consentFileId":2,
"projectId":5,
"consentDescription":"r",
"consentFileName":"test.pdf",
"servicePathToGetConsentPdf":null
},
{
"consentFileId":3,
"projectId":5,
"consentDescription":"rrr",
"consentFileName":"test.pdf",
"servicePathToGetConsentPdf":"localhost:8080/4c_viewFile?consentFileId=3"
}
],
[
{
"anonymized_patient_identifier":"r",
"projectId":5
},
{
"anonymized_patient_identifier":"2",
"projectId":5
},
{
"anonymized_patient_identifier":"5",
"projectId":5
}
]
]
I have managed to get values from simpler JSON strings but this one has multiple levels and also there is no key in each level. I tried with simple code like this:
Object obj = parser.parse(data);
JSONObject jsonObject = (JSONObject) obj;
resultJson = (String) jsonObject.get("projectId");
resultJson += "\n";
resultJson += (String) jsonObject.get("userName");
but I get the error [java.lang.ClassCastException: org.json.simple.JSONArray cannot be cast to org.json.simple.JSONObject] And also I don't understand how I will get the values in lower level without a key. I tried also to save it as a JSONArray but it didn't work.
your root of json is type of JSONArray,
the first object stored in the root array is an object, you can retrieve it by using index = 0 .
this is a hack to make your code work:
JSONArray jsonArray = JSONArray.fromObject(data);
JSONObject jsonObject=obj.getJSONObject(0);
resultJson = (String) jsonObject.get("projectId");
resultJson += "\n";
resultJson += (String) jsonObject.get("userName");
NOTE:
to convert a String to JSONArray, you can do :
JSONArray array = JSONArray.fromObject(data);
To improve on nafas answer, I would do this to see all the objects in the array:
Object obj = parser.parse(data);
JSONArray jsonArray = (JSONArray) obj;
for (int i = 0; i < jsonArray.size (); i++) {
JSONObject jsonObject=obj.getJSONObject(i);
resultJson = (String) jsonObject.get("projectId");
resultJson += "\n";
resultJson += (String) jsonObject.get("userName");
}