how to make fault tolerant code when parsing JSONObject? - java

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
}

Related

Parsing JSON object from service call Spring 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!

How to have special character in JSON

Here I have shown the sample JSON object of my project
{
"objectType": "main",
"description": "",
"Column": "[{"displayName": "Account Name", "DataType" : "string"}, {"displayName" : "Billing City", "DataType" : "string" }, { "displayName" : "Billing State/Province" , "DataType" : "string" }, {"displayName" : "Billing Street", "DataType" : "textarea"}]"
}
It has some special characters like"/" (Billing State/Province) in the display name. Now it was not allowed to convert it to JSONArray and put in the RootJsonObject due to the special character in it. I had used the following code
RootJsonObject = new JSONObject();
RootJsonObject.put("content",new JSONArray(JsonObject.getString("Column")));
But I need that special character. Is there is any other way to have that "/" in my JSONObject or can I use any other JSON util.
I can see you've updated your question to include valid JSON for the Content property.
When deserialising this string to JSON, you will need to escape any special characters.
Apache StringEscapeUtils contains an escapeJson method which can do this for you:
RootJsonObject = new JSONObject();
String jsonArrayString = StringEscapeUtils.escapeJson(JsonObject.getString("Column"));
RootJsonObject.put("content", new JSONArray(jsonArrayString));
I am not 100% clear where JsonObject comes from or is populated but if the above does not work, you may need to escape the content earlier in the process somewhere.

AngularJS: passing complex json data using $http.post

I'm having trouble passing a complex json object in angularjs with $http.post. I'm keep getting a 400 bad request error sent back from the server saying the request was syntactically incorrect. I believe it has something to do with the array since it passes fine when i don't include it.
json i'm passing.
{
customer: {
firstName: "John",
lastName: "Doe",
street: "1234 South Dr",
city: "Detroit",
state: "MI",
zip: "12345",
phone: "123-321-1234",
email: "EMAIL#GMAIL.COM"
},
order: {
orderDate: "06-16-2015",
registerNum: "1",
transactionNum: "7820",
deliveryStatusID: 1,
notes: "Hold order until July",
items: [
{skuID: "1234568",
skuDescription: "Order item 1",
qty: "4",
itemStatusID: 1,
itemStatusDescription: "Backorder"
},
{skuID: "7387491",
skuDescription: "Order item 2",
qty: "1",
itemStatusID: 1,
itemStatusDescription: "Flagged"
}
]
}
}
angular service function
this.addOrder = function(new_order) {
return $http.post(base + "/add", new_order);
};
Spring MVC controller method
#RequestMapping(value="/add", method=RequestMethod.POST)
public void addOrder(#RequestBody CustomerOrder customerOrder) {
System.out.println("----CUSTOMER-INFO----");
System.out.println(customerOrder.getCustomer().getFirstName());
System.out.println(customerOrder.getCustomer().getLastName());
System.out.println("");
System.out.println("----ORDER-INFO----");
System.out.println(customerOrder.getOrder().getOrderID());
System.out.println(customerOrder.getOrder().getOrderDate());
}
The problem only seems to occur when I pass the items array in the json. I've passed the same json object without the items array and it works fine. The format of the json is being sent in the same format that gets returned whenever I GET an order with my angularjs service method so I'm really not sure as to where I'm going wrong with this.
If I need to provide more code please let me know. I appreciate any effort in helping me out.
Thank you.
Jason
Well after struggling to find my error in this problem, I finally found a solution. I thought I'd share how I debugged and fix this problem in case someone else is in a similar situation as I was.
After trying every possible way of sending my data in angular to the server and continually getting the same HTTP 400 error, I decided to send the json as a string and accept the json as a string in my spring mvc controller like this.
angular service method:
this.addOrder = function(new_order) {
return $http.post(base + "/add", angular.toJson(new_order));
};
spring controller
#RequestMapping(value="/add", method=RequestMethod.POST, consumes="application/json")
public void addOrder(#RequestBody String json) {
}
From here I simply took the json passed in and used the Jackson ObjectMapper to convert the json string to my POJO like this.
mapping json string to pojo
#RequestMapping(value="/add", method=RequestMethod.POST, consumes="application/json")
public void addOrder(#RequestBody String json) {
ObjectMapper mapper = new ObjectMapper();
try {
CustomerOrder order = mapper.readValue(json, CustomerOrder.class);
System.out.println(order.getCustomer().getFirstName() + " " + order.getCustomer().getLastName());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
After doing this and running my code, I would get an UnrecognizedPropertyException on a field in my Items class when trying to bind the items json to the List in my Order class. It was just a simple mispelling on the json side and I completely missed it. After correcting this, jackson mapped everything correctly and I no longer get this HTTP 400 Error The request was syntactically incorrect.
Another thing to note is that if you pass your object as a string in angular using the JSON.stringify you may encounter this same exception on hashKey field in the JSON object. The hashKeys are used by angular to monitor changes. I believe you can use a jackson annotation to ignore unknown fields or you can simply use angular.toJson instead which will remove all the hasKey/values for you which is what I did.
Just formatted the Json in a better way. Try this if it helps. Also, post the java classes if possible:
{
"customer": {
"firstName": "John",
"lastName": "Doe",
"street": "1234 South Dr",
"city": "Detroit",
"state": "MI",
"zip": "12345",
"phone": "123-321-1234",
"email": "EMAIL#GMAIL.COM"
},
"order": {
"orderDate": "06-16-2015",
"registerNum": "1",
"transactionNum": "7820",
"deliveryStatusID": 1,
"notes": "Hold order until July",
"items": [
{
"skuID": "1234568",
"skuDescription": "Order item 1",
"qty": "4",
"itemStatusID": 1,
"itemStatusDescription": "Backorder"
},
{
"skuID": "7387491",
"skuDescription": "Order item 2",
"qty": "1",
"itemStatusID": 1,
"itemStatusDescription": "Flagged"
}
]
}
}

Json parser error? Amazon API incorrect JSON response?

So here is the code I use to parse the amazon JSON response for my inventory of products.
ListInventorySupplyResponse response = client.listInventorySupply(request);
ResponseHeaderMetadata rhmd = response.getResponseHeaderMetadata();
String responseJSON = response.toJSON();
JSONParser parser = new JSONParser();
try {
json = (JSONObject) parser.parse(responseJSON);
It worked for a week, and then I got this error today.
Unexpected token VALUE(-1) at position 5948.
looking through the response JSON. I put it in a JSON validator (http://jsonlint.com/)
jsonlint told me that the response I was getting was not correct json! Here was the error
{
"SellerSKU": "zz",
"FNSKU": "B006T5BLTO",
"ASIN": "B006T5BLTO",
"Condition": "NewItem",
"TotalSupplyQuantity": 92,
"InStockSupplyQuantity": 44,
"EarliestAvailability": {
"TimepointType": "DateTime",
"DateTime": 2015-01-13T09: 00: 00Z
},
"SupplyDetail": {
"member": [
]
}
},
{
"SellerSKU": "yyC",
"FNSKU": "B00IHMDJ7Y",
"ASIN": "B00IHMDJ7Y",
"Condition": "NewItem",
"TotalSupplyQuantity": 63,
"InStockSupplyQuantity": 63,
"EarliestAvailability": {
"TimepointType": "Immediately"
},
"SupplyDetail": {
"member": [
]
}
},
Parse error on line 398:
... "DateTime": 2015-01-13T09: 00: 00Z
----------------------^
Expecting '}', ',', ']'
As you can see, for some reason most of products are available immediately but one is not and Amazon sends me a "datetime" for when it is. However they dont put the date time in quotes making it an invalid JSON.
Is it me? Is it them? How do I handle this. My program doesnt need this part of the JSON but I dont know how to take this field out or tell the parser to "skip over it" so that it can parse the rest of the fields minus this one incorrect field that I dont care about anyway.
Thanks!

Parse simple JSON

I have a trouble to parse this piece of JSON
{
"00408C88A2E6": {
"id": "00408C88A2E6",
"name": "pippo"},
"00408C91188B": {
"id": "00408C91188B",
"name": "pluto"
},
"00408C944B99": {
"id": "00408C944B99",
"name": "minni"
},
"00408C944BA0": {
"id": "00408C944BA0",
"name": "topolino"
}
I need to get all the key "id" and "name", I tried with an iterator but I was able to retrive just the first dicts (00408C88A2E6,00408C91188B...), could anyone give me any hint?
Thank you
Edit:
I'm using org.json and to parse this I tried in this way
JSONObject jsonChannels = getHttpJson(url_user_cam);
ArrayList<String> al = new ArrayList<String>();
Log.i(LOG_TAG, jsonChannels.toString());
try{
Iterator<String> iterator = jsonChannels.keys();
while (iterator.hasNext() ){
al.add(iterator.next());
}
}catch(Exception e){
Log.e(LOG_TAG, e.toString());
}
with this piece of code my intent is to get the first dict ("00408C88A2E6") after make it I need to access to "id" and "name" element, hwo can i do it?
As pointed in the comments, it looks like your JSON is incomplete. Maybe a pasting error ?
Do you do it manually or do you use a library ?
Have you tried using the "official" Java JSON package ?

Categories

Resources