Parsing JSON object from service call Spring JAVA - java

I am getting the following response from some service call . I am trying to parse the JSON . I am actually new to JAVA and not sure about how to parse JSON objects returned from HTTP call . I am getting the following error :
org.json.JSONException: JSONArray initial value should be a string or collection or array.
at org.json.JSONArray.<init>(JSONArray.java:197) ~[json-20180813.jar!/:na]
Code :
Object resp = hiveApiClient.getEnrollmentSearchDetails(certificate, employeeId);
logger.info("response : " + resp);
JSONArray mainArray = new JSONArray(resp);
// The nested array is at the second position : 1
JSONArray nestedArray = mainArray.getJSONArray(1);
// the interesting main JSONObject is on the first position
// of the nested array : 0
JSONObject interestingJSONObject = nestedArray.getJSONObject(0);
logger.info("XXX :{}", interestingJSONObject);
String courseId = interestingJSONObject.getJSONObject("additionalData").getString("courseId");
logger.info("XXXX :{}",courseId);
return courseId;
Response :
[
"list", [{
"#type": "com.saba.services.calendar.CalendarElementDetail",
"eventType": "ILTCLASS",
"elementName": "Microservice Application Architecture",
"elementId": "class000000000013497",
"eventId": "timel000000000103609",
"ownerID": "emplo000000000096641",
"locationId": "locat000000000003165",
"locationName": "IND-Bangalore-Karnataka",
"additionalData": {
"#type": "map",
"locationTimeZone": "tzone000000000000042",
"eventID": "class000000000013497",
"locationName": "IND-Bangalore-Karnataka",
"locationId": "locat000000000003165",
"transcriptID": "ofapr000000002962367",
"registrationID": "regdw000000001766254",
"eventName": "Microservice Application Architecture",
"moduleID": "regmd000000002147176",
"courseID": "cours000000000031995"
},
"startDate": {
"#type": "com.saba.customtypes.DateWithLocale",
"date": 1538613000000,
"locale": "03-OCT-2018",
"timeInLocale": "8:30 PM",
"dateInUserTimeZone": "03-OCT-2018",
"timeInUserTimeZone": "5:30 PM",
"dateInCustomTimeZone": null,
"timeInCustomTimeZone": null,
"customTimeZoneDate": 0,
"timeInStandardFormat": "8:30 PM",
"dateInStandardFormat": "10/03/2018"
}
}]
]

Well first of all, your json is not valid because of this}:
["list" : /* something here but anyway, not the concern here */ ]
when it should have been
{"list" : /* something here but anyway not the concern here */}
I think your problem is with the understanding of how a JSON file works and what is a json object and a json array. Please correct your JSON input so that we can provide you with insights on how to retrieve the value you need.
Additionally, I would recommend you looking into Jackson lib for parsing JSON objects to JAVA POJOs directly really easily. The link is a great tutorial to get you started here. Furthermore, jackson is already included with Spring so that you literally have nothing to install.
Edit
I misread the JSON input : I saw a : after "list" instead of a ,.
So your JSON is a proper JSON but its a quite uncommon JSON as it is loosely typed and therefore cannot be that easily parsed with standard Jackson library for example. In fact, in the main array, a string is put together with a Json Object which is a very bad practice but that's not your fault as I suppose you are not responsible for the output of this HTTP call.
So how can you actually get your value ? Well let's describe the JSON, you've got here : a JSON array containing a String and another sub JSON array. You want to take some values from the very first JSON object inside the nested json array.
This one :
{
"#type": "com.saba.services.calendar.CalendarElementDetail",
"eventType": "ILTCLASS",
"elementName": "Microservice Application Architecture",
"elementId": "class000000000013497",
"eventId": "timel000000000103609",
"ownerID": "emplo000000000096641",
"locationId": "locat000000000003165",
"locationName": "IND-Bangalore-Karnataka",
"additionalData": {
"#type": "map",
"locationTimeZone": "tzone000000000000042",
"eventID": "class000000000013497",
"locationName": "IND-Bangalore-Karnataka",
"locationId": "locat000000000003165",
"transcriptID": "ofapr000000002962367",
"registrationID": "regdw000000001766254",
"eventName": "Microservice Application Architecture",
"moduleID": "regmd000000002147176",
"courseID": "cours000000000031995"
},
"startDate": {
"#type": "com.saba.customtypes.DateWithLocale",
"date": 1538613000000,
"locale": "03-OCT-2018",
"timeInLocale": "8:30 PM",
"dateInUserTimeZone": "03-OCT-2018",
"timeInUserTimeZone": "5:30 PM",
"dateInCustomTimeZone": null,
"timeInCustomTimeZone": null,
"customTimeZoneDate": 0,
"timeInStandardFormat": "8:30 PM",
"dateInStandardFormat": "10/03/2018"
}
}
The first task here is to gather this object. Let's suppose the nested json array is always in the second position after the string and that the JSON object you want is always at the first position of the nested array which might not be the case depending on your input JSON but this was not precised in your question.
JSONArray mainArray = new JSONArray(resp);
// The nested array is at the second position : 1
JSONArray nestedArray = mainArray.getJSONArray(1);
// the interesting main JSONObject is on the first position
// of the nested array : 0
JSONObject interestingJSONObject = nestedArray.getJSONObject(0);
So now we want "courseId" from "additionnalData" Json Object :
String courseId = interestingJSONObject.getJSONObject("additionalData").getString("courseId");
And there you go!

Related

how to make fault tolerant code when parsing JSONObject?

currently I retrieve a JSON object from algolia like this to my app:
{
"title": "Manajemen Masjid sesuai sunnah Rasulullah",
"address": "Jl. Tebet Utara I No.40, RT.8/RW.2, Tebet Tim., Tebet, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12820, Indonesia",
"additionalAddress": "",
"capacity": 0,
"city": "Jakarta",
"creatorIsVerified": true,
"description": "Dua aplikasi milik Facebook",
"email": "abcd#gmail.com",
"eventID": "000b4e1a-f65e-4d77-83ce-d0770d344d4b",
"eventType": "Kajian Umum",
"_geoloc": {
"lat": -6.2256428,
"lng": 106.8527658
},
"hasBeenApproved": true,
"numberOfContact": "081808664",
"price": 0,
"rankPoint": 300000000,
"speaker": "Syafiq Reza Basalamah",
"venue": "Aql Islamic Center 2",
"website": "http://www.lakuin.id"
}
as you can see, in this record, there is no "instagram" field in the JSON above. but other records have "instagram" field in the JSON. I have problem when parsing that JSON in my Android app because not all data has "instagram" field in it.
I parse the "instagram" field using this code, If the "instagram" field is not available from incoming JSON, then I want to assign an empty string like the code below:
val instagram = jsonObject.get("instagram") as? String ?: ""
the jsonObject data type is java class JSONObject (import org.json.JSONObject)
but that line will make a crash. error message:
Caused by: org.json.JSONException: No value for instagram
E/CrashlyticsCore: Unexpected method invoked on
AppMeasurement.EventListener: onEvent(java.lang.String,
java.lang.String, android.os.Bundle, java.lang.Long); returning null
so how to write code that can handle both case, either it has "instagram" field or not from the incoming json ?
As #Pemba Tamang suggested, use jsonObject.optString("instagram",""); or use gson library, it handles errors in json
You can use try , catch for that :
try{
// try to parse ur Json here
}catch (JSONException e){
// here you can assign the empty String
}

Json Transformation in java with high performance

I need to transform a Json into another Json according to the parameter coming as part of Rest request. This service is developed in Java. I know, Jackson API can be used easily and there are some libraries also available. But my requirement is to delivery response with new Json faster as much as possible.
If I can be given few option I can measure the performance of those.
Let's assume I have this Json in data storage:
{
"bookId": "23228232-2dfa232",
"bookName": "Json Transformation",
"bookPublisher": "Tech Publication",
"bookRating": [
{
"source": "All book rank",
"maxRating": "10",
"rating": "3.4"
},
{
"source": "Tech Books",
"maxRating": "5",
"rating": "2"
},
{
"source": "Popular",
"maxRating": "3",
"rating": "1"
}
],
"bookAuthor": [
{
"name": "Jone",
"specialities": [
"Json",
"Javascript",
"Typescript",
"nodejs"
]
},
{
"name": "Mike",
"specialities": [
"Java",
"Spring",
"ElasticSearch"
]
}
]
}
Below rest calls should have respective results from this Json:
Get only authors
/authorName/23228232-2dfa232
{
authorName: [
"Jone",
"Mike"
]
}
Get Average Rating
/popularity/23228232-2dfa232
{
rating: "1.78"
}
So, the question is how to do this kind of transformation efficiently with any available library? As I mentioned above, I can simply use any Json library in Java and transform the Json, but I am not sure, if that will be efficient.
You can try little json java library for searching json data.
JsonValue json = JsonParser.parse(stringvariablewithjsondata);
List<JsonValue> authors = json.findAll(SPM.path("bookAuthor", "name")));
List<String> ratings = json.findAllLiterals(SPM.path("bookRating", "rating")));
and compute result like
JsonArray values = JsonFactory.array();
for(JsonValue value : authors) values.add(value);
JsonObject result = JsonFactory.object().add("authorName", values);
return result.toCompactString()
You can use JSON-Java --> https://www.baeldung.com/java-org-json
Or the Google JSON, aka GSON and a few others as listed here --> https://javarevisited.blogspot.com/2016/09/top-5-json-library-in-java-JEE.html
To see popularity and use statistics, which might help you chose which ones to test first: https://www.baeldung.com/java-json
You can use GSON as it easily maps JSON with POJO classes (Especially nested ones)
For a quick reference for performance comparison,

Remove a String from Json Object

I am trying to convert an Avro Kafka Event to Json and need to manipulate The Avro Event by Removing Strings from this Event.
I am using GSON Library to manipulate the Json String Object but somehow its not removing the intended String.
JsonElement je = new Gson().fromJson(matchRequest, JsonElement.class);
JsonObject jo = je.getAsJsonObject();
jo.remove("com.XXX.XXXX");
jo.remove("com.XXX.XXX");
jo.remove("com.XXX.XXX");
System.out.println("#################"+jo);
Json String I am Receiving as matchRequest is
{"interaction_id":"321","customer_id":"32","context_id":"123","work_id":"ewq","work_request_id":"213","task_type":"123","match_type":"wert","resource_list":{"com.xxx.xxxx":{"rank":1,"resource_data":{"com.xxx.xxxx":{"account_id":1,"source_name":"Mankind","channel_id":"voice"}}}},"service_list":{"com.xxx.xxxx":{"rank":5,"priority":1,"resource_count":"gvk","min_proficiency":"10","max_proficiency":"1","attributes":{"com.xxx.xxxx":{"category":"edw","value":"33232"}},"resource_offered":{"com.xxx.xxxx":{"agent_id":"rewq","account_id":"123","source_name":"wqe","resource_address":"ewq","source_address":"rewq","channel_id":"212","channel_provider":"wqe"}}}},"matching_state":"OFFERED"}
JSON Format
"interaction_id": "321",
"customer_id": "32",
"context_id": "123",
"work_id": "ewq",
"work_request_id": "213",
"task_type": "123",
"match_type": "wert",
"resource_list": {
"com.XXXXXX": {
"rank": 1,
"resource_data": {
"com.XXXX": {
"account_id": 1,
"source_name": "Mankind",
"channel_id": "voice"
}
}
}
},
"service_list": {
"com.XXXX": {
"rank": 5,
"priority": 1,
"resource_count": "gvk",
"min_proficiency": "10",
"max_proficiency": "1",
"attributes": {
"com.XXXX": {
"category": "edw",
"value": "33232"
}
},
"resource_offered": {
"com.XXXX": {
"agent_id": "rewq",
"account_id": "123",
"source_name": "wqe",
"resource_address": "ewq",
"source_address": "rewq",
"channel_id": "212",
"channel_provider": "wqe"
}
}
}
},
"matching_state": "OFFERED"
}
When you look at the documentation of the remove() method, it needs a key from the JSON object in parameter.
However, the JSON you are receiving does not contain "com.xxx.xxxx" as key, but some keys, like "resource_list", are linked to another JSON object containing "com.xxx.xxxx" as a key.
You may want to look recursively into the JSON object you receive to remove the intended String.
You need to perform your operation over your array:
jo.getAsJsonObject("resource_list").remove("com.XXX.XXXX");
This should do the trick.

Parsing nested json array in java

I have json file in below format.
{
"data":[
{
"prjId": 1,
"name" : "Forj1",
"issue": [
{
"id": 00001,
"status" : "Closed"
},
{
"id": 00002,
"status" : "Open"
}
]
},
{
"prjId": 2,
"name" : "Forj2",
"issue": [
{
"id": 00003,
"status" : "Closed"
},
{
"id": 00004,
"status" : "Open"
}
]
}],
"issueCounter": 7,
"success": true
}
Here "data" is array of projects, and within project attribute there is array of "issue".
So far if I remove "issue" array, I am able to traverse the json to one level down in "data" attribute, If this json has "issue" array I get an error saying missing comma.
javax.json.stream.JsonParsingException: Invalid token=NUMBER at (line no=15, column no=14, offset=242) Expected tokens are: [COMMA]
Below is the code that I have right now. I have two problems with this, one is the error while reading if I place the "issue" attribute, and secondly a way to read the "issue" array and traverse all attributes within.
InputStream fis = new FileInputStream(pathToFile+"data3.json");
JsonReader jsonReader = Json.createReader(fis);
//the error is thrown on below line while reading the above json.
JsonObject jsonObject = jsonReader.readObject();
jsonReader.close();
fis.close();
System.out.println(jsonObject.getInt("issueCounter"));
//reading arrays from json
JsonArray jsonArrayData = jsonObject.getJsonArray("data");
Project [] prj = new Project[jsonArrayData.size()];
int index = 0;
for(JsonValue value : jsonArrayData){
JSONObject jsonObj = new JSONObject(value.toString());
System.out.println(jsonObj.getString("name"));
System.out.println(jsonObj.getInt("prjId"));
//this is also the place where I am stuck, I know I need to construct an array out of it by obtaining issue attribute. Below is very very wrong.
/*
JsonArray jsonArrayIssue = jsonObj.getJsonArray("issue");
for(JsonValue issue : jsonArrayIssue){
JSONObject jsonIssueObj = new JSONObject(issue.toString());
System.out.println(jsonIssueObj.getString("status"));
System.out.println(jsonIssueObj.getInt("id"));
}
*/
}
Any help or pointers is deeply appreciated. I can tweak the json if its required ultimately I need to maintain an array of issues.
The problem as others said is the JSON.
"id": 00001 <-- this is a number, numbers cannot start with a leading zero as per JSON stadard.
If you control the JSON you should tweak it.
Alternatively ff you don't, you can use a less strict parser like org.json.simple https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple
The code will be the same as yours, just adjusted to org.json.simple
try { ...
JSONObject rootJSON = (JSONObject) new JSONParser().parse(jsonString);
JSONArray dataList = (JSONArray) rootJSON.get("data");
for(Object projectObj: dataList.toArray()){
JSONObject project = (JSONObject)projectObj;
JSONArray issueList = (JSONArray) project.get("issue");
for(Object issueObj: issueList.toArray()){
JSONObject issue = (JSONObject) issueObj;
//do something with the issue
}
}
} catch (ParseException e) {
//do smth
e.printStackTrace();
}
Your json data is invalid.You can check here.
http://jsonlint.com
...issue": [{ "id": 00001,
"status": ----------------------^
Your id must be string number,string,boolean.Send 1,2,3,.... as return values and check if it works.
Your code looks okay the problem is the JSON formatting. Specifically the following lines:
"id": 00001,
"id": 00002,
"id": 00003,
"id": 00004,
Basically if you want it in that format you will need to set them as strings by wrapping the values in quotations i.e. "id": "00001" or you can use a valid number i.e. "id": 1

JSON different objects in an array

At the moment i'm trying to understand json and how it works.
But i have a problem with an array of objects.
all objects in the array have a key called "value" (i know it's weird, it's not my code) what also is an object.
And now to the problem: This object called "value" has always different key-values.
So i dont now how i can parse the json code to java object code, when it differ, every time.
Here some examples:
First object of the array:
"value":
{
"local":
[
"English", "Deutsch", Espanol"
],
"english":
[
"English", "Deutsch", Espanol"
],
},
Second object(now a string, not object) of the array:
"value" : "",
Third object of the array:
"value" : {},
...
Maybe I'm doing the parsing wrong.
First I have created the beans classes in java for the json code and then I'm using the automatic parser of google. (gson)
It works when only one of the examples above is inside the json code. (it should not differ, like changing from string to object...)
Gson gson = new Gson();
Output output = gson.fromJson(json, Output.class);
Output is the main class for the json stuff.
I have found out that maybe while parsing I could check a value called "id" first, and from that I could create another beans class with the right variables ...
Thats the code i need to parse to java objects and how do you do that??
The problem is the key called "value", because its always different.
With my method of using the google parser "gson" it wont work, because i'm getting exception that its an string but i was waiting for an object...
{
"status":"success",
"data":{
"panel":{
"title":{
"label":{ "local":"Tote Selection", "english":"Tote Selection" },
"image":"public/img/pick.jpg", "type":"default"
},
"isFirst":false, // currently not used
"isLast":false, // currently not used
"ownCount":0, // currently not used
"panelsCount":0, // currently not used
"elements":[
{
"type":"text",
"id":"1", "value":{ "local":"Scan next order tote",
"english":"Scan next order tote" },
"label":{ "local":"", "english":"" }, "color":"000000",
"fontsize":18, "fontstyle":"flat", "alignment":"left",
"rows":"undefined", "bgcolor":"", "isFocus":false
},
{
"type":"text",
"id":"4", "value":{ "local":"Scan tote: ", "english":"Scan tote: " },
"label":{ "local":"", "english":"" }, "color":"000000", "fontsize":20,
"fontstyle":"strong", "alignment":"left", "rows":"undefined",
"bgcolor":"", "isFocus":false
},
{
"type":"input",
"id":"6", "value":"", "label":{ "local":"", "english":"" },
"color":"000000", "fontsize":24, "fontstyle":"flat", "alignment":"left",
"rows":"undefined", "isFocus":true
},
{
"type":"button",
"id":"1", "value":{ "local":"", "english":"" },
"label":{ "local":"Menu", "english":"Menu" }, "color":"000000",
"fontsize":14, "fontstyle":"strong", "alignment":"left",
"rows":"undefined", "isFocus":false
},
{
"type":"button",
"id":"4", "value":{ "local":"", "english":"" },
"label":{ "local":"Enter", "english":"Enter" }, "color":"000000",
"fontsize":14, "fontstyle":"strong", "alignment":"right",18
"rows":"undefined", "isFocus":false
}
]
},
"authToken":"0fdd440a-619f-4936-ab74-d189accb5bd9",
"routing":{
"controller":"panel",
"action":"process",
"workflowId":"singlepicking",
"taskId":"orderSelection"
}
}
}
Thank you for your help!
it looks a little bit different but your answer helped me! Thx
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(br).getAsJsonObject();
//now getting all the json values
String status = obj.get("status").getAsString();
JsonObject data = obj.getAsJsonObject("data");
String authToken = data.get("authToken").getAsString();
JsonObject routing = data.getAsJsonObject("routing");
String controller = routing.get("controller").getAsString();
String action = routing.get("action").getAsString();
String workflowId = routing.get("taskId").getAsString();
If I understood ur question properly u can retrieve the values of the JSONArray as below
for (int i = 0; i < JArray.length(); i++) {
print(JArray.getJSONObject(i).tostring())
}
So if i am right u are getting the JSON from a String First?? so please try below first store the String in JSONObject as JSONObject obj = new JSONObject(str);//str is the string that u are getting
to get the valueenglish that are in data-panel-tittle-label is
String englishinLable=obj .getJSONObject("data").getJSONObject("panel").getJSONObject("title").getJSONObject("label").optString("english")

Categories

Resources