How do I get multiple optional values of JSON data? - java

There is a JSON data that contains several optional fields:
My code to get these values is:
String name = null;
String family_name = null;
String given_name = null;
String suffix_name = null;
try {
JSONObject contact = new JSONObject("{\"givenName\":[\"John\"],\"familyName\":[\"Doe\"]}");
name = contact.getJSONArray("name").getString(0);
family_name = contact.getJSONArray("familyName").getString(0);
given_name = contact.getJSONArray("givenName").getString(0);
suffix_name = contact.getJSONArray("honorificPrefix").getString(0);
} catch (JSONException e) {
Log.e("ContactsManager", "Failed to parse json data: "+e);
}
The problem here is, if "name" is null(as the example above), all other fields will failed to be retrieved, which is not I expected.

why not add a check before reading
if (contact.has("name")) {
name = contact.getJSONArray("name").getString(0);
}

Related

Java - JSONArray has 10 objects but only display first two

I'm new to Android and Java so I'm building a demo app of book listing to learn about parsing JSON data. I use log to check how many books there are on data (which is 10 ) but only get 2 first books on the list displayed when running it on an emulator... Hope anyone can tell me where I should change?
Thanks for any opinion!
E/QueryUtils: length of array: 10
The API link: https://www.googleapis.com/books/v1/volumes?q=search+terms
QueryUtils.java
private static List<BookItem> extractItemFromJson(String bookJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(bookJSON)){
return null;
}
// Create an empty ArrayList that we can start adding books to
List<BookItem> bookItems = new ArrayList<>();
// Try to parse the JSON response string. If there is a problem with the way the JSON is formatted,
// a JSONException exception object will be thrown.
// Catch the exception so the app doesnt crash, and prent the error message to the logs.
try {
JSONObject baseJsonresponse = new JSONObject(bookJSON);
JSONArray bookItemArray = baseJsonresponse.getJSONArray("items");
Log.e("QueryUtils", "length of array: " + bookItemArray.length());
for (int i = 0; i < bookItemArray.length(); i++) {
JSONObject currentBook = bookItemArray.getJSONObject(i);
JSONObject volumeInfo = currentBook.getJSONObject("volumeInfo");
String title = volumeInfo.getString("title");
String subtitle = volumeInfo.getString("subtitle");
String previewLink = volumeInfo.getString("previewLink");
JSONObject imageLinks = volumeInfo.getJSONObject("imageLinks");
String thumbnail = imageLinks.getString("smallThumbnail");
BookItem book = new BookItem(/**author, */title, subtitle, thumbnail, previewLink);
bookItems.add(book);
}
} catch (JSONException e) {
Log.e("QueryUtils", "Problem parsing the earthquake JSON results", e);
}
return bookItems;
}
The third book in your list does not cointain the field imageLinks, and that causes an exception.
You should add a check:
String thumbnail = "";
if (volumeInfo.has("imageLinks")) {
JSONObject imageLinks = volumeInfo.getJSONObject("imageLinks");
thumbnail = imageLinks.getString("smallThumbnail");
}
I suspect it's going to the catch block after parsing the first 2 because an exception happened while parsing, You should fix the exception and also you can catch the exception inside the loop to add the items that could be parsed and don't quit the loop if there is a JSONException.

how to iterate json String

I have an array of JSON strings like:
[{
"id":"BirthDate",
"field":"BirthDate",
"type":"date",
"input":"text",
"operator":"equal",
"value":"2016/04/07"
}]
I want to be able to iterate this array and want to get its id, field, value in Java
Using the below code I got an exception
"json object must begin with {"
String rules=helper.getRules();
System.out.println("====Rulses=====:"+rules);
try {
JSONObject obj = new JSONObject(rules);
System.out.println("====obj===="+obj);
// boolean error = obj.getBoolean("error");
String id = obj.getString("id");
System.out.println("===id is===: "+id);
} catch (JSONException e){
e.printStackTrace();
}
You should instead create a JSONArray from the String and then iterate over the array. Modify your code as
String rules=helper.getRules();
System.out.println("====Rulses=====:"+rules);
try {
// create the json array from String rules
JSONArray jsonRules = new JSONArray(rules);
// iterate over the rules
for (int i=0; i<jsonRules.length();i++){
JSONObject obj = jsonRules.get(i);
System.out.println("====obj===="+obj);
String id = obj.getString("id");
System.out.println("===id is===: "+id);
}
} catch (JSONException e){
e.printStackTrace();
}
Try this parsing your rulesinto a JSONArray:
String rules = "[{\"id\":\"BirthDate\",\"field\":\"BirthDate\",\"type\":\"date\",\"input\":\"text\",\"operator\":\"equal\",\"value\":\"2016/04/07\"}]";
try {
JSONArray obj = new JSONArray(rules); // parse the array
for(int i = 0; i < obj.length(); i++){ // iterate over the array
JSONObject o = obj.getJSONObject(i);
String id = o.getString("id");
System.out.println("===id is===: " + id);
}
} catch (JSONException e){
e.printStackTrace();
}
In the JSON you gave as example you just have one element in your array.

Modifying/Updating values inside a jsonArray?

What I want to do is at a particular index position change/replace a value inside a json array.After going through the documentation at http://www.json.org/javadoc/org/json/JSONArray.html I found out that jsonArray does not have a getIndex() method.In this situation how do I update my json array at a given index position.
This is the method that creates a json array in my android code.
private void createJsonArray() {
billType = (invEstSwitch.isChecked() ? textViewEstimate : textViewInvoice)
.getText().toString();
String invNumber = textViewInvNo.getText().toString();
String bcode = barCode.getText().toString();
String description = itemDesc.getText().toString();
String wt = weightLine.getText().toString();
String rateAmt = rateAmount.getText().toString();
String making = makingAmount.getText().toString();
String netr = netRate.getText().toString();
String iTotal = itemtotal.getText().toString();
String vatAmt = textViewVat.getText().toString();
String sumAmt = textViewSum.getText().toString();
String crtDate = textViewCurrentDate.getText().toString();
try {
jsonObject.put("custInfo", custSelected.toString());
jsonObject.put("invoiceNo", invNumber);
jsonObject.put("barcode", bcode);
jsonObject.put("description", description);
jsonObject.put("weight", wt);
jsonObject.put("rate", rateAmt);
jsonObject.put("makingAmt", making);
jsonObject.put("net_rate", netr);
jsonObject.put("itemTotal", iTotal);
jsonObject.put("vat", vatAmt);
jsonObject.put("sum_total", sumAmt);
jsonObject.put("bill_type", billType);
jsonObject.put("date", crtDate);
} catch (JSONException e) {
e.printStackTrace();
}
try {
itemSelectedJson.put(index, jsonObject);
index++;
} catch (JSONException e) {
e.printStackTrace();
}
}
And this is the code that I use to update my json array which contains a json object.
try {
itemSelectedJson.getJSONObject(i).put("net_rate",netChange);
Log.d("NETRATE_TW",itemSelectedJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
Now the problem with this code is it updates the jsonArray everytime a new item is added to the code.So the first object values are the same as the last object.
Also note that I am using this code inside a text watcher.So the afterTextchanged() method looks like this.
#Override
public void afterTextChanged(Editable s) {
String netChange = netRate.getText().toString();
final int row_id = (int) newRow.getTag();
if ((row_id<0) || (row_id> itemSelectedJson.length())){
return;
}
try {
itemSelectedJson.getJSONObject(row_id-1).put("net_rate",netChange);
Log.d("NETRATE_TW",itemSelectedJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
};
This is the snapshot of what my database looks like.
A jSONObject(which is a collection of name,value pairs) can be converted into a JSONArray which is an ordered array of the "values" in the JSONObject.
This can be done using the .toJSONArray() method.
When you need to replace/update the JSONArray, you may use the method
.put(int index, java.util.Map value)
Unlike how you are doing at present, i.e getting the object and setting a new key and value.
http://www.json.org/javadoc/org/json/JSONArray.html#put(int, java.util.Map)
As I understood, your problem is in creating multiple JSONObjects in your JSONArray with the same values, and that's because you can't get the index of a created JSONObject inside your JSONArray, and to overcome this problem, you can easily create a compound JSONObject that contains your JSONObjects instead of a JSONArray contains JSONObjects, and the object name will be anything unique in your JSONObject data, and when you make any changes or add any item it will either be added as a new object if it doesn't exist or it will overwrite the existing object if it added before, for example let's suppose that barcode value is unique in your data, so the code will be like the following:
// declaring itemSelectedJson as JSONObject
JSONObject itemSelectedJson = new JSONObject();
.
.
.
// when wanting to add a new item
itemSelectedJson.put(jsonObject.getString("barcode"), jsonObject);
and to retrieve the data you simple iterate through this JSONObject:
Iterator<?> keys = itemSelectedJson.keys();
JSONObject single_item;
while(keys.hasNext()) {
String key = (String)keys.next();
single_item = itemSelectedJson.getJSONObject(key);
// do what do you want here
}

Java - Parsing JSON Response - Content is either String or JSONObject

I am facing a typical scenario while parsing JSON Response for one of the Service calls.
The content for one of the attributes (from below example, consider "name" as a attribute) coming as either String or JSONObject.
How to handle these kind of scenarios through code. Also, please consider that json content need not be consistent with same set of attributes.
Example:
String Response
{"name":"Adam"}
JSON Response
{"name":{"FirstName":"Adam", "MiddleName":"Don"} }
OR
{"name":{"FirstName":"Adam", "LastName":"Don"} }
OR
{"name":{"MiddleName":"Adam", "LastName":"Don"} }
You can ask the root JSONObject with the method optJSONObject(name) to return a JSONObject for the given name if it exists and is an JsonObject. Otherwise you can also test with optString(name) for a String.
So something like:
JSONObject root = new JSONObject(... data from server ... );
JSONObject obj = root.optJSONObject("name");
if (obj != null) {
// Do something with the object
} else {
String name = root.getString("name");
// Do something with the string
}
Parse your response JSON as a JSONObject, then get another JSONObject for the "name" key, if it throws a JSONException then your object is probably a String in with case you can call get String for the "name" key in your catch block.
String name = "";
JSONObject serverJSON = new JSONObject(YOUR_JSON_RESPONSE_STRING_FROM_SERVER);
try {
JSONObject nameObject = serverJSON.getJSONObject("name");
if (nameObject.has("first_name")) {
name = nameObject.getString("first_name") + " ";
}
if (nameObject.has("middle_name")) {
name += nameObject.getString("middle_name") + " ";
}
if (nameObject.has("last_name")) {
name += nameObject.getString("last_name");
}
name = name.trim();
} catch (JSONException e) {
// Probably a String, try again...
try {
name = serverJSON.getString("name");
catch (JSONException e) {
// Not a String or a JSONObject... figure out what's wrong...
e.printStackTrace();
}
}
I would really recommend though, that if you have any control of the server that you make sure that the name key choose one type and sticks to it; a JSONObject... You would be able to use the has(String key) member function in if statements to properly find all of your data without knowing what existed at runtime...
EDIT: Thought of a different idea... Parse the String to the first colon and see if the next non-whitespace character is a quotation mark, if it is, then your key belongs to a String, if it is a curly brace then it's a JSONObject. (If neither, then you have an error, because you aren't expecting an array or number or null or anything else...)
boolean jsonIsString = true;
String searchString = json.substring(json.indexOf(":")).trim();
if ("{".equals(searchString.charAt(0)) {
jsonIsString = false;
}
Tonity's solution is good. You can also use this solution.
In my solution, there will be no any Exception fired until JSON is wrong. What I am doing is following.
Search for number of ":" in string.
If it returns 1, then we sure that there is "name" value.
Otherwise, we need to check, whether there is "FirstName","MiddleName" or "LastName" exist in string or not.
Just go through this snippet and you will find solution for your problem.
// String str = "{\"name\":\"chintan\"}";
String str = "{\"name\":{\"FirstName\":\"Chintan\",\"LastName\":\"Rathod\"}}";
try {
//we will check how many ":" are there in string, if it is one, then
// we are going to get "name" field.
if ((str.split(":").length - 1) == 1)
{
Log.d("Home", "1");
JSONObject json = new JSONObject(str);
Log.d("Home", "Name : " + json.get("name"));
}
else
{
Log.d("Home", "more then 2");
JSONObject jName = new JSONObject(str);
JSONObject jTemp = jName.getJSONObject("name");
if (jTemp.toString().contains("FirstName"))
Log.d("Home", "FirstName :" + jTemp.getString("FirstName"));
if (jTemp.toString().contains("MiddleName"))
Log.d("Home","MiddleName :" +jTemp.getString("MiddleName"));
if (jTemp.toString().contains("LastName"))
Log.d("Home", "LastName :" + jTemp.getString("LastName"));
}
} catch (JSONException e) {
e.printStackTrace();
}
Output
08-06 11:52:34.060: D/Home(1439): more then 2
08-06 11:52:34.060: D/Home(1439): FirstName :Chintan
08-06 11:52:34.070: D/Home(1439): LastName :Rathod
I faced a problem like this as well. I didn't want to parse the JSON manually. Do this if firstName exists otherwise do that. I didn't want to mess up my structure because I only define java object and my client handles the parsing. So, I came up with following:
#Getter
#Setter
#ToString
class Response {
private Name name;
#Getter
#Setter
#NoArgsConstructor
#ToString
public static class Name {
private String name;
private String firstName;
private String middleName;
private String lastName;
public Name(String name) {
this.name = name;
}
}
}
Then, parse the json;
ObjectMapper objectMapper = new ObjectMapper();
Response response = objectMapper.readValue(json, Response.class);
Now, string response and JSON response can be parsed with the same class.

How to get specific JSON data?

Hi I am trying to read JSON from an ReST API but Im getting a nullpointer exception because mycode is not correct.
I have a JSON that I am reading from looking like this :
processJSON({
"LocationList":{
"noNamespaceSchemaLocation":"http://api.vasttrafik.se/v1/hafasRestLocation.xsd",
"servertime":"16:13",
"serverdate":"2013-03-22",
"StopLocation":[{
"name":"Brunnsparken, Göteborg",
"lon":"11.967824",
"lat":"57.706944",
"id":"9021014001760000",
"idx":"1"
},{
"name":"Brunnsgatan, Göteborg",
"lon":"11.959455",
"lat":"57.693766",
"id":"9021014001745000",
"idx":"4"
},{
"name":"Brunnslyckan, Lerum",
"lon":"12.410219",
"lat":"57.812073",
"id":"9021014017260000",
"idx":"5"
},
Now I want the name from the JSON document depending on what the user inputs.
how do I do this with code?
My code that is wrong is like this :
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
public class JSONReader {
private String jsonData = "";
public String getJsonData(String location){
try {
URL url = new URL("http://api.vasttrafik.se/bin/rest.exe/v1/location.name?authKey=secret&format=json&jsonpCallback=processJSON&input=" + URLEncoder.encode(location, "UTF-8"));
URLConnection connection = url.openConnection();
BufferedReader readJsonFile = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String temp = "";
while((temp = readJsonFile.readLine()) != null){
jsonData += temp;
}
readJsonFile.close();
System.out.println(jsonData);
return jsonData;
}
catch (IOException e) {
}
return null;
}
public void JSONParsing(){
String location = Planner.getPlanner().getStartingLocation();
JSONObject obj =(JSONObject)JSONValue.parse(getJsonData(location));
//Set the text into the JList
if (obj.containsValue(location));
obj.get("name");
}
}
I want get the same name of the location out from the JSON as the user inputs.
How do I do this with code?
I think that you are asking how to parse your JSONObject and get the corresponding values out of it that the user is interested in. Below is an example of how you can pull apart the JSONObject to create a Map whose key is the String id (since the name does not seem to be unique) and whose value is the whole JSONObject. You can use this map to lookup the input from the user and find the appropriate LLA if that's what you are interested in.
public Map<String, JSONObject> createLocationMap(JSONObject jsonObj){
Map<String, JSONObject> nameToLocationMap = new HashMap<String, JSONObject>();
JSONObject locationList = (JSONObject) jsonObj.get("LocationList");
JSONArray array = (JSONArray) locationList.get("StopLocation");
for (int i = 0; i < array.length(); i++) {
String name = (String) ((JSONObject) array.get(i)).get("id");
nameToLocationMap.put(name, ((JSONObject)array.get(i)));
}
return nameToLocationMap;
}
You can tailor this method as you see fit. For example if you are interested in the relationship between the id and the name then you can create a similar method that uses those values instead of id and the entire JSONObject'. I hope that this helps~

Categories