Related
I am trying to Parse below JSON data to String in Java using (GSON) Library, I am able to parse all JSON fields data except one of the JSON Array. I want to check if it's null/empty then in String variable store null value, if it's not then store the original value.
Input JSON Data:
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 37875,
"issues": [
{
"id": "1190",
"key": "GDS-81",
"fields": {
"issuetype": {
"id": "2170",
"name": "Service Request with Approvals",
"subtask": false
},
"customfield_29805": {
"id": "26",
"name": "Issue - First Response",
"completedCycles": []
}
}
}
]
}
Code that I have done so far,
JsonObject object = (JsonObject) new JsonParser().parse(jsonResponse);
JsonArray issuesArray = object.getAsJsonArray("issues");
for(int i=0; i<issuesArray.size(); i++) {
JsonObject currentissues = (JsonObject) issuesArray.get(i);
String Issue_Id = (String) currentissues.get("id").toString().replace("\"", "");
String Issue_Key = (String) currentissues.get("key").toString().replace("\"", "");
String Issue_Type = (String) currentissues.get("fields").getAsJsonObject().get("issuetype").getAsJsonObject().get("name").getAsString();
JsonObject customfield = (JsonObject) currentissues.get("fields").getAsJsonObject().get("customfield_29805");
JsonArray completedCyclesArray= customfield.getAsJsonArray("completedCycles");
String Issue_FirstResponseStartTime = (completedCyclesArray.size() > 0) ? completedCyclesArray.getAsString() : "NULL";
}
However when I execute code I get below error on line :JsonObject customfield
java.lang.ClassCastException: com.google.gson.JsonNull cannot be cast to com.google.gson.JsonObject
[![UpdatedCode StackTrace][1]][1]
[1]: https://i.stack.imgur.com/2wY0S.jpg
you dont need to explicitly , cast JsonElement to JsonObject instead use getAsJsonArray , Once you get your array, you can iterate through all the elements of it.
You also need to handle null check for completedCyclesArray before checking its siz else it will give you the NPE , I have fixed that as well.
Please find the modified working code as below
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(jsonResponse).getAsJsonArray();
for(JsonElement e : array) {
JsonObject currentissues = (JsonObject) e;
String Issue_Id = (String) currentissues.get("id").toString().replace("\"", "");
String Issue_Key = (String) currentissues.get("key").toString().replace("\"", "");
String Issue_Type = (String) currentissues.get("fields").getAsJsonObject().get("issuetype").getAsJsonObject().get("name").getAsString();
JsonObject customfield = (JsonObject) currentissues.get("fields").getAsJsonObject().get("customfield_29805");
JsonArray completedCyclesArray= customfield.getAsJsonArray("completedCycles");
String Issue_FirstResponseStartTime = (null != completedCyclesArray && completedCyclesArray.size() > 0) ? completedCyclesArray.getAsString() : "NULL";
}
}
Please find my working solution for the updated json request(which not an array but nested json request)
JsonObject object = (JsonObject) new JsonParser().parse(jsonResponse);
JsonArray issuesArray = object.getAsJsonArray("issues");
String expand = object.get("expand").toString();
String startAt = object.get("startAt").toString();
String maxResults = object.get("maxResults").toString();
String total = object.get("total").toString();
System.out.println(String.format("expand %s , startAt %s, maxResults %s, total %s", expand, startAt, maxResults, total));
IntStream.range(0, issuesArray.size()).mapToObj(i -> (JsonObject) issuesArray.get(i)).forEach(currentissues -> {
String Issue_Id = (String) currentissues.get("id").toString().replace("\"", "");
String Issue_Key = (String) currentissues.get("key").toString().replace("\"", "");
String Issue_Type = (String) currentissues.get("fields").getAsJsonObject().get("issuetype").getAsJsonObject().get("name").getAsString();
JsonObject customfield = (JsonObject) currentissues.get("fields").getAsJsonObject().get("customfield_29805");
JsonArray completedCyclesArray = customfield.getAsJsonArray("completedCycles");
String Issue_FirstResponseStartTime = (completedCyclesArray.size() > 0) ? completedCyclesArray.toString() : "NULL";
System.out.println(String.format("Issue_Id %s , Issue_Key %s, Issue_Type %s, Issue_FirstResponseStartTime %s", Issue_Id, Issue_Key, Issue_Type, Issue_FirstResponseStartTime));
});
and this is the output I got :
expand "schema,names" , startAt 0, maxResults 50, total 37875 Issue_Id
1190 , Issue_Key GDS-81, Issue_Type Service Request with Approvals,
Issue_FirstResponseStartTime NULL
Please see my complete working code here complete code
for both the secnarios
Empty completedCycles
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 37875,
"issues": [
{
"id": "1190",
"key": "GDS-81",
"fields": {
"issuetype": {
"id": "2170",
"name": "Service Request with Approvals",
"subtask": false
},
"customfield_29805": {
"id": "26",
"name": "Issue - First Response",
"completedCycles": []
}
}
}
]
}
Non Empty completedCycles
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 37875,
"issues": [
{
"id": "1190",
"key": "GDS-81",
"fields": {
"issuetype": {
"id": "2170",
"name": "Service Request with Approvals",
"subtask": false
},
"customfield_29805": {
"id": "26",
"name": "Issue - First Response",
"completedCycles": [{"name":"abc"},{"name": "xyz"}]
}
}
}
]
}
Try adding getAsJsonObject() at the end of that statement.
Okay, so I need to put many different lists into one list using Java. Here is the important code.
String jsonText = buffer.toString(); // gets what the URL returns as JSON
JSONObject obj = new JSONObject(jsonText); // using JSONObject to pass to a JSONArray to search for the JSON
List<List<String>> allInfo = new ArrayList();// list to put all the returned information
List<String> innerList = new ArrayList();
JSONArray linemanques = obj.getJSONArray("linemanques"); //selects the array to read from
for (int i = 0; i < linemanques.length(); i++) {
JSONObject questionParts = linemanques.getJSONObject(i);
quesnum = questionParts.getString("quesnum"); // all of questionParts.getString() are for getting the data in the JSONArray
questype = questionParts.getString("questype");
question = questionParts.getString("question");
ans1 = questionParts.getString("ans1");
ans2 = questionParts.getString("ans2");
ans3 = questionParts.getString("ans3");
ans4 = questionParts.getString("ans4");
correctans = questionParts.getString("correctans");
category = questionParts.getString("category");
notes = questionParts.getString("notes");
flag = questionParts.getString("flag");
innerList.add(quesnum);
innerList.add(questype);
innerList.add(question);
innerList.add(ans1);
innerList.add(ans2);
innerList.add(ans4);
innerList.add(correctans);
innerList.add(category);
innerList.add(notes);
innerList.add(flag);
allInfo.add(innerList);
}
return allInfo;
As shown above, I take a List called innerList and put it into another List, which is of type List called allInfo. In the for loop, I take the length of the JSONArray I'm using, and add the elements to innerList. Then, I take innerList and add it into allInfo, then return that.
By the way, here is the JSON.
{
"error": false,
"message": "Request successfully completed",
"linemanques": [
{
"quesnum": 1,
"questype": 1,
"question": "This is question #1",
"ans1": "This is answer 1",
"ans2": "This is answer 2\r\n",
"ans3": "This is answer 3\r\n\r\n\r\n",
"ans4": "This is answer 4",
"correctans": "ans4",
"notes": "This is a note",
"category": "2",
"flag": "ans4"
},
{
"quesnum": 2,
"questype": 2,
"question": "This is question #2",
"ans1": "This is Q2 ans 1",
"ans2": "This is Q2 ans2",
"ans3": "This is Q2 ans3",
"ans4": "This is Q2 ans4",
"correctans": "ans2",
"notes": "This is Q2 note 1",
"category": "5",
"flag": "ans2"
},
{
"quesnum": 3,
"questype": 6,
"question": "gkjhgjkgkg",
"ans1": "ghdfhdghfd",
"ans2": "Tuituiyt",
"ans3": "Tiuytui9",
"ans4": "Tauitui.247",
"correctans": "ans2",
"notes": "Article iutuC",
"category": "5",
"flag": "ans2"
},
{
"quesnum": 7,
"questype": 2,
"question": " how many",
"ans1": "isi",
"ans2": "thiis\\r\\n",
"ans3": "yes",
"ans4": "no",
"correctans": "yes",
"notes": "refer back to yes",
"category": "0",
"flag": "yes"
},
{
"quesnum": 8,
"questype": 2,
"question": " how many",
"ans1": "isi",
"ans2": "thiis",
"ans3": "yes",
"ans4": "no",
"correctans": "yes",
"notes": "refer back to yes",
"category": "0",
"flag": "yes"
},
{
"quesnum": 9,
"questype": 2,
"question": "How many apples can I eat in one day?",
"ans1": "42 apples",
"ans2": "6 apples",
"ans3": "89 apples",
"ans4": " 42 oranges",
"correctans": "ans2",
"notes": "try eating apples",
"category": "8",
"flag": "ans2"
},
{
"quesnum": 10,
"questype": 2,
"question": " how many",
"ans1": "isi",
"ans2": "thiis\\r\\n\\r\\n\\r\\n",
"ans3": "yes",
"ans4": "no",
"correctans": "yes",
"notes": "refer back to yes",
"category": "0",
"flag": "yes"
}
]
}
And this is the structure of the array I'm hoping for:
allInfo {
innerList {
JSONObject
JSONObject
JSONObject
}
innerList {
JSONObject
JSONObject
JSONObject
}
innerList {
JSONObject
JSONObject
JSONObject
}
innerList {
JSONObject
JSONObject
JSONObject
}
innerList {
JSONObject
JSONObject
JSONObject
}
innerList {
JSONObject
JSONObject
JSONObject
}
}
But instead, this is what I'm ending up with (i think):
allInfo {
innerList {
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
JSONObject
}
}
It's supposed to make multiple lists in one list so that I can call access to it and set text in a TextView like this:
textView.setText(allInfo.get(2).get(4)); //example
I guess if you place the line List<String> innerList = new ArrayList(); within the for loop, it will properly initialize the innerList each time.
I think you do it in a hard way.
you could use a library to deserializes your JSON like Jackson
So you could build pojo class out your keys
import com.fasterxml.jackson.databind.ObjectMapper;
class Pojo {
String quesnum;
int questype;
String question;
String ans1;
String ans2;
String ans3;
String no;
String correctans;
String notes;
int category;
String flag;
}
then use Jackson to do the job for you by calling
List<Pojo> allInfo = mapper.readValue(json, new TypeReference<List<Pojo>>() {});
If i understood correctly, you forget to clean innerList within for loop. You need to do:
innerList.clear()
I have the following JSON Information.
{
"version": 2,
"locations": [{
"id": "750",
"geo": {
"name": "Lord Howe Island",
"state": "Lord Howe Island",
"country": {
"id": "au",
"name": "Australia"
},
"latitude": -31.557,
"longitude": 159.086
},
"astronomy": {
"objects": [{
"name": "moon",
"days": [{
"date": "2018-09-05",
"events": [],
"moonphase": "waningcrescent"
}]
}]
}
}]
}
What I wish to do is print to a textView just a few details in the JSON (Not All), so my desired output is the following:
Name: Lord Howe Island
Country: Australia
Moon Phase: Waning Crescent
However, I do not have any luck when parsing the information to be printed in the textView. I am currently using the following code:
JSONArray JA = new JSONArray(data);
for (int i = 0; i < JA.length(); i++) {
JSONObject JO = (JSONObject) JA.get(i);
JSONObject geo = JO.getJSONObject("geo");
JSONObject astronomy = JO.getJSONObject("astronomy");
singleParsed = "Name:" + geo.get("name") + "\n" +
"Latitude:" + JO.get("latitude") + "\n" +
"Longitude:" + JO.get("longitude") + "\n" +
"Phase: " + astronomy.get("moonphase") + "\n";
}
Then showing the data with the following:
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity.fetcheddata.setText(this.singleParsed);
}
}
I can print all of the data just using
MainActivity.fetcheddata.setText(this.data);
However I do also see the tags in the textView and ALL Information, not the few tags I am after.
What Am I doing wrong?
All help is much appreciated
Edit: This was suggested, currently working on it.
JSONArray JA = new JSONArray(data);
for (int i = 0; i < JA.length(); i++) {
JSONObject JO = (JSONObject) JA.get(i);
JSONObject astronomy = JO.getJSONObject("astronomy");
JSONArray objects = astronomy.getJSONArray("objects");
JSONArray days = objects.getJSONObject(0).getJSONArray("days");
Object moonphase = days.getJSONObject(0).get("moonphase");
moon = "Name:" + days.get(Integer.parseInt("moonphase"));
}
The problem you're running into is you're trying to use JSONObjects, even though locations is an array, as is objects.
For this to work, you will need to iterate over the array as such:
JSONObject jo = new JSONObject(yourData);
JSONArray locations = jo.getJSONArray("locations");
for (int i = 0; i < locations.length(); ++i) {
//iterate over each key, etc.
}
In my opinion, at the end of the day, this will be a mess, and a pain to maintain if you change keys, add keys, etc. I'd recommend looking into something like GSON, and then creating just viewmodels of the data you want. In the end you would end up with something as such:
List<T> yourObjects = gson.fromJson(jsonReader, X[].class);
Then you can individually access any property you want.
cannot get moonphase directly from astronomy , [] will define an array, so you could do like this:
"astronomy": {
"objects": [{
"name": "moon",
"days": [{
"date": "2018-09-05",
"events": [],
"moonphase": "waningcrescent"
}]
}]
}
JSONObject astronomy = JO.getJSONObject("astronomy");
JSONArray objects = astronomy.getJSONArray("objects");
JSONArray days = objects.getJSONObject(0).getJSONArray("days");
JSONObject moonphase = days.getJSONObject(0).get("moonphase");
Assuming your json data as it is and your output as you wrote above:
JSONArray locations = data.getJSONArray("location");
JSONObject loc = locations.getJSONObject(0);
JSONObject geo = loc.getJSONObject("geo");
JSONObject country = geo.getJSONObject("country");
JSONObject astronomy = loc.getJSONObject("astronomy");
JSONObject objects = astronomy.getJSONArray("objects").getJSONObject(0);
JSONObject day = objects.getJSONArray("days").getJSONObject(0);
StringBuilder result = new StringBuilder();
String singleParsed = "Name:" + geo.getString("name") + "\n" +
"Country: " + country.getString("name") +
"Moon Phase: " + astronomy.getString("moonphase") + "\n";
I have received a json string like so:
{
"data": [
{
"name": "Order",
"value": "2"
},
{
"name": "Address",
"value": "182"
},
{
"name": "DNS",
"value": "null"
},
{
"name": "SSID",
"value": "work"
},
{
"name": "Protocol",
"value": "0"
},
{
"name": "Key",
"value": ""
},
{
"name": "carrier",
"value": "undefined"
},
{
"name": "SSH",
"value": "1"
},
{
"name": "ntp_addr",
"value": ""
},
{
"name": "Name",
"value": ""
}
]
}
I used stringify on an html response and this is what I have to parse. As you can see, it is pretty redundant; I would much rather { "Order":"2" } than { "name":"Order","value":"2" } ... So an array of name-value pairs, instead of an array of objects.
Is there a way I can dynamically format this response so that it will be easier to parse?
What 'd like is to be able to say:
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray data = jsonObject.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject dataObject = data.getJSONObject(i);
String order = dataObject.getString("Order");
String address = dataObject.getString("Address");
// etc...
}
But the current format makes it almost impossible to parse. I'd need loops within loops.
I'd like to use com.google.gson library. And this response easy to parse with it:
private final JsonParser PARSER = new JsonParser();
public void parse(String jsonString) {
JsonObject dataObject = PARSER.parse(jsonString).getAsJsonObject();
JsonArray dataArray = dataObject.get("data").getAsJsonArray();
dataArray.iterator().forEachRemaining(element -> {
String name = element.getAsJsonObject().get("name").getAsString();
String value = element.getAsJsonObject().get("value").getAsString();
}
}
Or you can simply use TypeAdapters for json deserialization directly in the object.
Something like this should do the trick
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray data = jsonObject.getJSONArray("data");
JSONObject simplifiedDataObject = new JSONObject();
for (int i = 0; i < data.length(); i++) {
JSONObject dataField = data.getJSONObject(i);
simplifiedDataObject.put(dataField.getString("name"), dataField.get("value"));
}
You just iterate over each element in data, use the name field as the field on a new JSONObject and simply retrieve the value using the value key.
I'm trying to grab the 'name' from the JSON snippet I've included. I have tried the following but what I'm expecting is never grabbed.
Edit: 'output' is the full JSON string in case it wasn't already understood ;)
JSONObject result = null;
JSONArray data = null;
try {
try {result = new JSONObject(output);} catch (JSONException e) {e.printStackTrace();}
try {
data = result.getJSONArray("data");
for(int a=0;a<data.length();a++){
System.out.println(result.getJSONObject(String.valueOf(a)).getString("name"));//getJSONObject("results")
}
Here is the JSON snippet I'm trying to work with:
{
"code": 200,
"status": "Ok",
"copyright": "© 2015 MARVEL",
"attributionText": "Data provided by Marvel. © 2015 MARVEL",
"attributionHTML": "Data provided by Marvel. © 2015 MARVEL",
"etag": "b130a8b7af591e4e7ca078753f9c5c8a76e55e5d",
"data": {
"offset": 0,
"limit": 20,
"total": 1485,
"count": 20,
"results": [
{
"id": 1011334,
"name": "3-D Man",
"description": "",
"modified": "2014
.
.
.
.
.
.
.
.
.
.
To get you started, "data" points to a JSON Object, not array. So it should be:
data = result.getJSONObject("data");
Then, "results" points to a JSON array:
JSONArray results = data.getJSONArray("results");
Then you can try your loop. You shouldn't be turning a into a String - getJSONObject() takes an int for the index.
In case you're confused between Objects and Arrays, a JSON object has key - value pairs and are enclosed in curly braces. The keys are strings and the values can be a mix of any type:
{"key1": 5, "key2": "value2", "key3": {
"anotherObject": [1,2,3,4]
}
}
An array is a list of objects and is enclosed in square brackets:
[{...}, {...}, {...}]
The elements in the list don't have to be JSON objects, and in good JSON they will all be of the same type:
[1,2,3,4,4] or ["we", "are", "in", "an", "array"]
JSONTokener jsonTokener = new JSONTokener(jsonVaule);
JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();
Int code =jsonObject.getInt("code");
String status =jsonObject.getString("status");
//{obejcet,obejcet,...}
for data{} is the same way~
JSONObject dataJsObject = (JSONObject) jsonObject.getJsonObject("data");
int offset =dataJsObject.getInt(""iffset);
....
//[{},{}] this type is jsonArrary
JSONArray results = dataJsObject.getJSONArray("results");
for(JSONObject resultJsonObj:JSONArray){
Int id =jsonObject.getInt("id");
//...and so on
}
hope it can help you~
You can parse like that
JsonObject obj = new JsonObject(StringResponse);
String code = obj.getString(code);
//same way you can get other string
JsonObject obj1 = obj.getJsonObject(Data);
String offset= obj.getString(offset);
//same way you can get other string
JsonArray jsonarr = obj1.getJsonArray(results);
for(i=0;i< jsonarr.size(); i++){
JsonObject innerObj = jsorr.getJsonObject(i);
String id= obj.getString(id);
//same way you can get other string
}
Hope It will helpful for you