2D JSON Array Not Generated in Correctly Java - java

I'm trying to generate 2d JSON Array in Java using Json Object, JSON Array. The 2d array being generated is valid but the ordering of elements is wrong.
Java Code...
JSONObject root1 = new JSONObject();
JSONObject c01 = new JSONObject();
JSONObject c11 = new JSONObject();
JSONObject attachment = new JSONObject();
JSONObject payload = new JSONObject();
JSONArray arrayButton= new JSONArray();
JSONArray arrayelements= new JSONArray();
JSONObject elementsObj = new JSONObject();
JSONObject defaultAction = new JSONObject();
root1.put("recipient", c01);
root1.put("message", c11);
c01.put("id", userId);
c11.put("attachment", attachment);
attachment.put("type", "template");
attachment.put("payload", payload);
payload.put("template_type", "generic");
payload.put("elements", arrayelements);
arrayelements.put(elementsObj);
elementsObj.put("title", "Sample Title");
elementsObj.put("image_url", "https://google.com/");
elementsObj.put("subtitle", "Sample Sub Title");
elementsObj.put("default_action", defaultAction);
defaultAction.put("type", "web_url");
defaultAction.put("url", "https://www.google.com/");
defaultAction.put("messenger_extensions", "true");
defaultAction.put("webview_height_ratio", "tall");
defaultAction.put("fallback_url", "https://www.google.com/");
elementsObj.put("buttons", arrayButton);
JSONObject buttons1 = new JSONObject();
buttons1.put("type", "web_url");
buttons1.put("url", "https://google.com");
buttons1.put("title", "show website");
arrayButton.put(buttons1);
JSONObject buttons2 = new JSONObject();
buttons2.put("type", "postback");
buttons2.put("title", "Hi There");
buttons2.put("payload", "sample payload");
arrayButton.put(buttons2);
Expected Output
{
"recipient":{
"id":"USER_ID"
},
"message":{
"attachment":{
"type":"template",
"payload":{
"template_type":"generic",
"elements":[
{
"title":"Sample title",
"image_url":"https://google.com/company_image.png",
"subtitle":"We\'ve got the right hat for everyone.",
"default_action": {
"type": "web_url",
"url": "https://google.com/",
"messenger_extensions": true,
"webview_height_ratio": "tall",
"fallback_url": "https://google.com/"
},
"buttons":[
{
"type":"web_url",
"url":"https://google.com",
"title":"View Website"
},{
"type":"postback",
"title":"Start Chatting",
"payload":"Sample payload"
}
]
}
]
}
}
}
}
Current Output
{
"recipient":{
"id":"988459377921053"
},
"message":{
"attachment":{
"payload":{
"elements":[
{
"buttons":[
{
"type":"web_url",
"title":"show website",
"url":"https://google.com"
},
{
"payload":"sample payload",
"type":"postback",
"title":"Hi There"
}
],
"image_url":"https://s3-ap-southeast-1.amazonaws.com/fls-items-dev/sample-item-4-95/post/sample-item-4-95-primary-4495.png",
"subtitle":"Sample Sub Title",
"title":"Sample Title",
"default_action":{
"fallback_url":"https://www.frrndlease.com/",
"webview_height_ratio":"tall",
"messenger_extensions":"true",
"type":"web_url",
"url":"https://www.frrndlease.com/ItemDetails?uid=wilson-kid-235"
}
}
],
"template_type":"generic"
},
"type":"template"
}
}
}
The order of buttons array, objects template_type & type are inverse. I'm creating nested Json objects and adding them from the outer level to the inner level still the output JSON is not as expected. Can't understand where I'm going wrong.

Related

Building ordered JSON string (GSON library)

Below is a simple example of how my JSON should look like . The object has string values for first name and last name, a number value for age and an array value of phone number objects.
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
Here is my code:
// creating JSONObject
JSONObject jsonObj = new JSONObject();
// putting data to JSONObject
jsonObj.put("firstName", "John");
jsonObj.put("lastName", "Smith");
jsonObj.put("age", 25);
// for phone numbers, first create JSONArray
JSONArray jsonArr = new JSONArray();
// create LinkedHashMap
Map<String,String> map = new LinkedHashMap<String, String>();
map.put("type", "home");
map.put("number", "212 555-1234");
// adding map to list
jsonArr.put(map);
map.put("type", "fax");
map.put("number", "212 555-1234");
// adding map to list
jsonArr.put(map);
// putting phoneNumbers to JSONObject
jsonObj.put("phoneNumbers", jsonArr);
// Instantiate a new Gson instance.
Gson gson = new Gson();
// writing JSON to file:"JSONExample.json" in cwd
String json = gson.toJson(jsonObj);
And this is what I'm getting:
{
"map":
{
"firstName":"John",
"lastName":"Smith",
"age":25,
"phoneNumbers":
{
"myArrayList":
[
{
"map":
{
"type":"home",
"number":"212 555-1234"
}
},
{
"map":
{
"type":"fax",
"number":"212 555-1234"
}
}
]
}
}
}
How can I ged rid of "myArrayList" and "map" in the JSON string?
UPDATE
I changed last part of the code:
// writing JSON to file:"JSONExample.json" in cwd
String json = jsonObj.toString();
And it works. But When I modify "firstName" to "first" like this:
// putting data to JSONObject
jsonObj.put("first", "John");
jsonObj.put("last", "Smith");
jsonObj.put("age", 25);
I'm getting disordered string which is weird.
{"last":"Smith","first":"John","age":25,"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"212 555-1234"}]}
I thought GSON library keeps the string ordered.
Try to use elegant-json. This library by default save order of elements.
This JSON:
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
can be made by this code:
new JsonObject()
.add("firstName", new JsonString("John"))
.add("lastName", new JsonString("Smith"))
.add("age", new JsonInt(25))
.add(
"phoneNumbers",
new JsonArray()
.add(
new JsonObject()
.add("type", new JsonString("home"))
.add("number", new JsonString("212 555-1234"))
)
.add(
new JsonObject()
.add("type", new JsonString("home"))
.add("number", new JsonString("212 555-1234"))
)
).toJson();
Note: JSON by definition is not ordered. So try not to depend on order of elements

Java Spring Boot - api object creation

I am working on a Java Spring boot api.
when the the call is made to get /api/home
I want to return this json sample structure.
var response = [
{
"type": "profile-breakdown",
"order": 0,
"grid-width": 6,
"grid-background": "",
"grid-background-url": "",
"title": "",
"contents": {
"name": "Name1",
"avatar" : 1,
"nextSDQ": 4,
"SQDCount": 3
}
},
{
"type": "current-standing",
"order": 1,
"grid-width": 6,
"grid-background": "",
"grid-background-url": "",
"title": "Your current standing summary",
"contents": {
"0": ["emotional distress", "behavioural difficulties", "hyperactivity and concentration difficulties", "difficulties in getting along with other young people"],
"4": ["kind and helpful behaviour"]
}
}
]
--
I've been building the various functions to get "profile-breakdown" and "current-standing" -- I want to append the responses to these to mimic the above structure.
so in MyService where /api/home gets RequestMapped to I begin to hook into my class MyApiHome
MyApiHome myApiHome = new MyApiHome();
JSONObject homeObj = myApiHome.getHomeData();
in MyApiHome -- I want to make "homeObj" in getHomeData an array as opposed to an JSONOBject - but then I start to fall into trouble with casts etc.. I want to build this in such a way - that if getProfileBreakDown is null or decoupled it isn't appended to the homeObj.
public class MyApiHome {
#SuppressWarnings("unchecked")
public JSONObject getHomeData(){
//build clean home object
JSONObject homeObj = new JSONObject();
homeObj.put("profile", this.getProfileBreakDown());
homeObj.put("currentstanding", this.getCurrentStanding());
//HashMap<List<String>, Object> hashMap = new HashMap<List<String>, Object>();
//hashMap.put())
return homeObj;
}
#SuppressWarnings("unchecked")
public Object getProfileBreakDown(){
//build clean home object
JSONObject contents = new JSONObject();
contents.put("name", "Name1");
contents.put("avatar", 1);
contents.put("nextSDQ", 4);
contents.put("SQDCount", 3);
//build clean home object
JSONObject json = new JSONObject();
json.put("type", "profile-breakdown");
json.put("order", 0);
json.put("grid-width", 6);
json.put("grid-background", "");
json.put("grid-background-url", "");
json.put("title", "");
json.put("contents", contents);
return json;
}
#SuppressWarnings("unchecked")
public Object getCurrentStanding(){
String[] stressArray1 = {"emotional distress", "behavioural difficulties", "hyperactivity and concentration difficulties", "difficulties in getting along with other young people"};
String[] stressArray2 = {"kind and helpful behaviour"};
//build clean home object
JSONObject contents = new JSONObject();
contents.put("0", stressArray1);
contents.put("4", stressArray2);
//build clean home object
JSONObject json = new JSONObject();
json.put("type", "current-standing");
json.put("order", 1);
json.put("grid-width", 6);
json.put("grid-background", "");
json.put("grid-background-url", "");
json.put("title", "Your current standing summary");
json.put("contents", contents);
return json;
}
}
To create an array of JSONs, we need to use JSONArray object which has a list of JSONObjects.
So using JSONArray.
I add to a json blob like a data stack.
JSONArray homeObj = new JSONArray();
if(this.getProfileBreakDown() != null){
homeObj.add(this.getProfileBreakDown());
}
if(this.getCurrentStanding() != null){
homeObj.add(this.getCurrentStanding());
}

How to create multi level JSON data using JSONObject in servlet

I need to create JSON data like below,
{
"min": {
"week": "1",
"year": "2014"
},
"max": {
"week": "14",
"year": "2017"
}
}
But JSONObject accepts only "id","value" format.
So how can I create JSON data using JSONObject like mentioned above.
That is very easy, here is an example:
JSONObject min = new JSONObject();
min.put("week", "1");
min.put("year", "2014");
JSONObject max = new JSONObject();
max.put("week", "14");
max.put("year", "2017");
JSONObject json= new JSONObject();
stats.put("min", min);
stats.put("max", max);
System.out.println(json.toString());
Tested this in eclipse already for you.
`
String s = "{ \"min\": { \"week\": \"1\", \"year\": \"2014\" }, \"max\": { \"week\": \"14\", \"year\": \"2017\" } }";
JSONParser parser = new JSONParser();
try {
JSONObject json = (JSONObject) parser.parse(s);
System.out.println(json.get("min"));
// this will output
//{"week":"1","year":"2014"}
} catch (Exception e){
e.printStackTrace();
}
`

org.json.JSONException: No value for Name JSON extraction error

I am getting this error when I try to get the value for "Name" out of the following JSON:
{
"edges": [
{
"node": {
"Name": "Sunday River",
"Latitude": 44.4672,
"Longitude": 70.8472
}
},
{
"node": {
"Name": "Sugarloaf Mountain",
"Latitude": 45.0314,
"Longitude": 70.3131
}
}
]
}
This is the snippet of code I am using to try and access these values, but I am just testing getting "Name" for now:
String[] nodes = stringBuilder.toString().split("edges");
nodes[1] = "{" + "\"" + "edges" + nodes[1];
String s = nodes[1].substring(0,nodes[1].length()-3);
Log.d(TAG, s);
JSONObject json = new JSONObject(s);
JSONArray jsonArray = json.getJSONArray("edges");
ArrayList<String> allNames = new ArrayList<String>();
ArrayList<String> allLats = new ArrayList<String>();
ArrayList<String> allLongs = new ArrayList<String>();
for (int i=0; i<jsonArray.length(); i++) {
JSONObject node = jsonArray.getJSONObject(i);
Log.d(TAG, node.toString(1));
String name = node.getString("Name");
Log.d(TAG, name);
}
My output looks like this:
{"edges":[{"node":{"Name":"Sunday River","Latitude":44.4672,"Longitude":70.8472}},{"node":{"Name":"Sugarloaf Mountain","Latitude":45.0314,"Longitude":70.3131}}]}}
{
"node": {
"Name": "Sunday River",
"Latitude": 44.4672,
"Longitude": 70.8472
}
}
org.json.JSONException: No value for Name
I understand that I could use optString and not get the error, but that will not give me the data stored in each node.
Here is a version that works with your unaltered JSON:
public static void main(String... args)
{
String json = "{\"data\":{\"viewer\":{\"allMountains\":{\"edges\":[{\"node\":{\"Name\":\"Sunday River\",\"Latitude\":44.4672,\"Longitude\":70.8472}},{\"node\":{\"Name\":\"Sugarloaf Mountain\",\"Latitude\":45.0314,\"Longitude\":70.3131}}]}}}}";
JSONObject obj = new JSONObject(json);
JSONObject data = obj.getJSONObject("data");
JSONObject viewer = data.getJSONObject("viewer");
JSONObject allMountains = viewer.getJSONObject("allMountains");
// 'edges' is an array
JSONArray edges = allMountains.getJSONArray("edges");
for (Object edge : edges) {
// each of the elements of the 'edge' array are objects
// with one property named 'node', so we need to extract that
JSONObject node = ((JSONObject) edge).getJSONObject("node");
// then we can access the 'node' object's 'Name' property
System.out.println(node.getString("Name"));
}
}

Android - How to parse specific values from JSON Array and display Toast

New to Android and Java in general and I'm learning how to make a JSON call. To do so, I'm following this guide: http://mobiforge.com/design-development/consuming-json-services-android-apps
Here's where things get confusing for me. The author of that tutorial wants the reader to call this API: http://ws.geonames.org/findNearByWeatherJSON?lat=37lng=122
Which returns a JSON object in this format:
{
"weatherObservation": {
"clouds":"scattered clouds",
"weatherCondition":"n/a",
"observation":"KCFV 090852Z AUTO 06005KT
10SM SCT090 SCT110 24/20 A3000 RMK AO2
SLP148 T02390200 53002",
"windDirection":60,
"ICAO":"KCFV",
"seaLevelPressure":1014.8,
"elevation":225,
"countryCode":"US",
"lng":-95.56666666666666,
"temperature":"23.9",
"dewPoint":"20",
"windSpeed":"05",
"humidity":78,
"stationName":"Coffeyville, Coffeyville
Municipal Airport",
"datetime":"2012-07-09 08:52:00",
"lat":37.083333333333336
}
}
Pretty straight forward, except that the API is no longer valid/has limits. In order to finish the project I've instead opted to call this API: http://api.openweathermap.org/data/2.5/weather?lat=37.77&lon=-122.419
Which returns the JSON in this format
{
"coord": {
"lon": 139,
"lat": 35
},
"sys": {
"country": "JP",
"sunrise": 1369769524,
"sunset": 1369821049
},
"weather": [
{
"id": 804,
"main": "clouds",
"description": "overcast clouds",
"icon": "04n"
}
],
"main": {
"temp": 289.5,
"humidity": 89,
"pressure": 1013,
"temp_min": 287.04,
"temp_max": 292.04
},
"wind": {
"speed": 7.31,
"deg": 187.002
},
"rain": {
"3h": 0
},
"clouds": {
"all": 92
},
"dt": 1369824698,
"id": 1851632,
"name": "Shuzenji",
"cod": 200
}
I can make the call just fine, but how do I display the "main" and "description" strings in the "weather" array? More specifically, how do I display this information as a Toast?
Here's what I have:
protected void onPostExecute(String result){
try {
JSONArray weatherArray = new JSONArray(result);
JSONArray wArray = new JSONArray("weather");
String mainWeather = wArray.getString(1);
String mainDescription = wArray.getString(2);
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.d("ReadWeatherJSONFeedTask", e.getLocalizedMessage());
}
BecauseI am following the mobiforge Tutorial, I have not deviated anywhere else except for this particular block of code.
Thanks for the help!
Edit:
There are several solutions here that work see #swats and #user3515851. I have chosen #remees-m-syde due to it's simplicity. Primarily because his solution did not require that I go through the for loop.
I have used optJSONArray or optString, instead of getJSONArray or getString as "opt" will return "" if there is no value for that key.. it will not throw any exception like in case of getString()
Try below code
JSONObject rootJsonObj = new JSONObject(result);
JSONArray wArray = rootJsonObj.optJSONArray("weather");
for (int i = 0; i < wArray.length(); i++) {
JSONObject weatherJsonObj = wArray.optJSONObject(i);
String mainWeather = weatherJsonObj.optString("main");
String mainDescription = weatherJsonObj.optString("description");
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();
}
Parsing issue was there, You should have taken object from response result.
EDIT: No need of try catch block while using optJSONArray or optString.
You are unable to get the data because there is one json object inside the "weather" JSONArray.
JSONArray starts with - [
JSONObject starts with - {,
So first get the JSONArray and then the JSONObject inside it.
"weather": [ ----Array
{ ----Object
"id": 804,
"main": "clouds",
"description": "overcast clouds",
"icon": "04n"
}
]
You have to get this JSONObject and then get the String from it like the below code showing.
JSONObject weatherArray = new JSONObject(result);
JSONArray wArray = weatherArray.getJSONArray("weather");
JSONObject jobj = wArray.getJSONObject(0);
String mainWeather = jobj.getString("main");
String mainDescription = jobj.getString("description");
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();
When there is multiple object in Array, Get it as below.
JSONObject rootJsonObj = new JSONObject(result);
JSONArray wArray = rootJsonObj.optJSONArray("weather");
for (int i = 0; i < wArray.length(); i++) {
JSONObject weatherJsonObj = wArray.getJSONObject(i);
String mainWeather = weatherJsonObj.getString("main");
String mainDescription = weatherJsonObj.getString("description");
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();
}
protected void onPostExecute(String result){
try {
JSONObject weatherArray = new JSONObject(result);
JSONArray wArray = weatherArray.getJSONArray("weather");
for(int i=0;i<wArray.length,i++){
JSONObject object=wArray.getJSONObject(i);
String mainWeather=object.getString("main");
String mainDescription=object.getString("description");
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.d("ReadWeatherJSONFeedTask", e.getLocalizedMessage());
}
I hope this one will help to you :)
I assume you obtained the weather array from parsing this JSON now to retrieve the values from it
JSONObject object=null;
try {
JSONObject object=array.getJSONObject(0);
String main=object.getString("main");
String description=object.getString("description");
} catch (JSONException e) {
e.printStackTrace();
}
and now use the strings in your toast
Assuming result contains the JSON, here is how to get main, and description form weather :
JSONObject resJSON = new JSONObject(result);
JSONArray weatherArray = resJSON.getJSONArray("weather");
for(int i = 0; i < weatherArray.length(); i++) {
JSONObject weatherJSON = weatherArray.getJSONObject(i);
System.out.println(weatherJSON.getString("main"));
System.out.println(weatherJSON.getString("description"));
}
Recently, I found out json2pojo useful tool for json parsing, works with anything Jackson,Gson,Java etc.
Hope this will help you.
Try this
JSONObject weatherObject = new JSONObject(result);
JSONArray wArray = weatherObject.getJSONArray("weather");
for (int i = 0; i < wArray.length(); i++) {
JSONObject wObject = wArray.getJSONObject(i);
if(wObject.has("description")) {
Log.d("TAG", wObject.getString("description"));
}
if(wObject.has("main")) {
Log.d("TAG", wObject.getString("main"));
}
}
Use this
JSONObject weatherArray = new JSONObject(result);
JSONArray wArray = new JSONArray("weather");
String mainWeather = ((JSONObject)wArray.getJSONObject(0)).getString("main");
String mainDescription = ((JSONObject)wArray.getJSONObject(0)).getString("description");
Toast.makeText(getBaseContext(), mainWeather + " - "
+ mainDescription,Toast.LENGTH_SHORT).show();

Categories