How to get nested JSON data within an array using Java? - java

I'm trying to get and print the values of Name and StarRating for each restaurant from the following JSON of which I've taken a snippet (there is more above this, however this is the relevant bit I'm trying to extract. Full link is available here API):
Restaurants": [
{
"Id": 89024,
"Name": "Regina Pizza",
"UniqueName": "regina-pizza-new-croydon",
"Address": {
"City": "Croydon",
"FirstLine": "309 Lower Addiscombe Road",
"Postcode": "CR0 6RF",
"Latitude": 51.382231,
"Longitude": -0.069915
},
"City": "Croydon",
"Postcode": "CR0 6RF",
"Latitude": 0.0,
"Longitude": 0.0,
"Rating": {
"Count": 561,
"Average": 5.18,
"StarRating": 5.18
}
I have the following method to get the data:
public static String parse(String responseBody) {
JSONArray restaurants = new JSONArray(responseBody);
for (int i = 0; i < restaurants.length(); i++) {
JSONObject restaurant = restaurants.getJSONObject(i);
String name = restaurant.getString("Name");
int rating = restaurant.getInt("StarRating");
System.out.println("Restaurant: " + name + " Rating: " + rating);
}
return null;
}
When running the code, I get an error indicating a JSONArray must start with '['.
I've tried to find similar examples of nested JSON, but I'm unable to find a relevant example.

Undercore-java will help.
String json = "{\"Restaurants\": [\n" +
"{\n" +
" \"Id\": 89024,\n" +
" \"Name\": \"Regina Pizza\",\n" +
" \"UniqueName\": \"regina-pizza-new-croydon\",\n" +
" \"Address\": {\n" +
" \"City\": \"Croydon\",\n" +
" \"FirstLine\": \"309 Lower Addiscombe Road\",\n" +
" \"Postcode\": \"CR0 6RF\",\n" +
" \"Latitude\": 51.382231,\n" +
" \"Longitude\": -0.069915\n" +
" },\n" +
" \"City\": \"Croydon\",\n" +
" \"Postcode\": \"CR0 6RF\",\n" +
" \"Latitude\": 0.0,\n" +
" \"Longitude\": 0.0,\n" +
" \"Rating\": {\n" +
" \"Count\": 561,\n" +
" \"Average\": 5.18,\n" +
" \"StarRating\": 5.18\n" +
" }" +
"}]}";
U.<List<Map<String, Object>>>get(U.fromJsonMap(json), "Restaurants").forEach(
restaurant -> System.out.println(restaurant.get("Name") + " "
+ U.get(restaurant, "Rating.StarRating"))
);
// output
// Regina Pizza 5.18

Consider using Java's JsonPath
And do something like (might need some tweaking)
Restaurants[name][StarRating]

Related

Spring query convert to a nested JSON structure

I'm new to spring and Java and trying to figure out how to go about formatting the json response into the desired structure.
I have a spring query that's returning 2 columns from a table like below which are really the key and values I need for the json structure:
Names
Values
Car
Toyota
Bike
Schwinn
Scooter
Razor
A0
11
A1
12
A2
13
B0
2000
B1
4000
B2
22000
The current json output from the controller is this:
[{
"names": "Car",
"values": "Toyota"
},
{
"names": "Bike",
"values": "Schwinn"
},
{
"names": "Scooter",
"values": "Razor"
},
{
"names": "A0",
"values": "11"
},
{
"names": "A1",
"values": "12"
},
{
"names": "A2",
"values": "13"
},
{
"names": "B0",
"values": "2000"
},
{
"names": "B1",
"values": "4000"
},
{
"names": "B2",
"values": "22000"
}
]
And the desired json format is this where the table column names are removed and instead json structure is created using the names column for the keys:
{
"Car": "Toyota",
"Bike": "Schwinn",
"Scooter": "Razor",
"Data": [{
"A0": "11",
"B0": "2000"
}, {
"A1": "12",
"B1": "4000"
}, {
"A2": "13",
"B2": "22000"
}]
}
Repository
#Query (value = "Select names, values ... :id")
List<Data> findData(#Param("id") Long id) ;
interface Data {
String getnames();
String getvalues();
}
Service
public List<Data> getData(Long id) {return repo.findData(id);}
Controller
#GetMapping("/getdata/{id}")
public ResponseEntity<List<Data>> getData(#PathVariable Long id) {
List<Data> c = service.getData(id);
return new ResponseEntity<>(c, HttpStatus.OK);
}
It seems that I need to process the result set and need to loop through them to create the desired structure but not sure how to proceed with that, or perhaps there is an easier way to get to the desired structure. Any guidance would be appreciated.
So return a ResponseEntity<Map<String, Object>> instead of a List to simulate a Json object.
List<Data> c = service.getData(id);
Map<String, Object> map = new HashMap<>();
map.put("Key", "Value");
map.put("Car", c.get(0).getvalues());
map.put("Entire List", c);
return new ResponseEntity<>(c, HttpStatus.OK);
Obviously you'll have to write your own logic but it should be pretty straight forward. Or, even better, consider making a class for the object returned if you're going to be using it a lot, and just return ResponseEntity< YourCustomObject >
This looks a bit complicated, I think you should set the primary key association for values like A0 B0
import com.black_dragon.utils.JacksonUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.groupingBy;
/**
* #author black_dragon
* #version V1.0
* #Package com.black_dragon.swing
* #date 2022/9/6 10:35
* #Copyright
*/
public class ConvertToMap {
String names;
String values;
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
public String getValues() {
return values;
}
public void setValues(String values) {
this.values = values;
}
private static String DIGIT_REGEX = "[^0-9]";
private static String LETTER_DIGIT_REGEX = "[a-zA-Z]+";
public static Integer getDigit(String str){
Pattern pattern = Pattern.compile(DIGIT_REGEX);
if(!isLetterDigit(str)){
String[] keySet = pattern.split(str);
if(keySet.length > 0){
return Integer.valueOf(keySet[1]);
}
}
return -1;
}
public static boolean isLetterDigit(String str){
return str.matches(LETTER_DIGIT_REGEX);
}
private static String fetchGroupKey(ConvertToMap convertToMap){
return String.valueOf(getDigit(convertToMap.names));
}
public static void main(String[] args) {
String jsonString = "[{\n" +
" \"names\": \"Car\",\n" +
" \"values\": \"Toyota\"\n" +
" },\n" +
" {\n" +
" \"names\": \"Bike\",\n" +
" \"values\": \"Schwinn\"\n" +
" },\n" +
" {\n" +
" \"names\": \"Scooter\",\n" +
" \"values\": \"Razor\"\n" +
" },\n" +
" {\n" +
" \"names\": \"A0\",\n" +
" \"values\": \"11\"\n" +
" },\n" +
" {\n" +
" \"names\": \"A1\",\n" +
" \"values\": \"12\"\n" +
" },\n" +
" {\n" +
" \"names\": \"A2\",\n" +
" \"values\": \"13\"\n" +
" },\n" +
" {\n" +
" \"names\": \"B0\",\n" +
" \"values\": \"2000\"\n" +
" },\n" +
" {\n" +
" \"names\": \"B1\",\n" +
" \"values\": \"4000\"\n" +
" },\n" +
" {\n" +
" \"names\": \"B2\",\n" +
" \"values\": \"22000\"\n" +
" }\n" +
"]";
List<ConvertToMap> convertToMaps = JacksonUtils.toJavaList(jsonString, ConvertToMap.class);
// Extract a string that does not contain numbers and convert it to a map
Map<String, Object> result = convertToMaps.stream()
.filter(x -> isLetterDigit(x.names))
.collect(Collectors.toMap(ConvertToMap::getNames, ConvertToMap::getValues));
List<Map<String, String>> mapList = new ArrayList<>();
// Group by string numbers containing numbers
Map<String, List<ConvertToMap>> stringListMap = convertToMaps.stream().collect(groupingBy(convertToMap -> fetchGroupKey(convertToMap)));
for (String key : stringListMap.keySet()) {
if(Integer.valueOf(key) >= 0){
mapList.add(stringListMap.get(key)
.stream()
.collect(Collectors.toMap(ConvertToMap::getNames, ConvertToMap::getValues)));
}
}
result.put("Data", mapList);
System.out.println(JacksonUtils.toJSONString(result));
}
}
Assume that your data key name pattern is one non-digit followed by digits.
https://github.com/octomix/josson
Deserialization
Josson josson = Josson.fromJsonString(
"[" +
" {" +
" \"names\": \"Car\"," +
" \"values\": \"Toyota\"" +
" }," +
" {" +
" \"names\": \"Bike\"," +
" \"values\": \"Schwinn\"" +
" }," +
" {" +
" \"names\": \"Scooter\"," +
" \"values\": \"Razor\"" +
" }," +
" {" +
" \"names\": \"A0\"," +
" \"values\": \"11\"" +
" }," +
" {" +
" \"names\": \"A1\"," +
" \"values\": \"12\"" +
" }," +
" {" +
" \"names\": \"A2\"," +
" \"values\": \"13\"" +
" }," +
" {" +
" \"names\": \"B0\"," +
" \"values\": \"2000\"" +
" }," +
" {" +
" \"names\": \"B1\"," +
" \"values\": \"4000\"" +
" }," +
" {" +
" \"names\": \"B2\"," +
" \"values\": \"22000\"" +
" }" +
"]");
Transformation
JsonNode node = josson.getNode(
"#collect([names !=~ '\\D\\d+']*" +
" .map(names::values)" +
" ,[names =~ '\\D\\d+']*" +
" .group(names.substr(1), map(names::values))#" +
" .elements" +
" .mergeObjects()" +
" .#toObject('Data')" +
")" +
".flatten(1)" +
".mergeObjects()");
System.out.println(node.toPrettyString());
Output
{
"Car" : "Toyota",
"Bike" : "Schwinn",
"Scooter" : "Razor",
"Data" : [ {
"A0" : "11",
"B0" : "2000"
}, {
"A1" : "12",
"B1" : "4000"
}, {
"A2" : "13",
"B2" : "22000"
} ]
}

Rest assured - How to validate JSON response field with the same name

I have the sample JSON response
"userinfo": [
{
"userName": "name1",
"registered": false
},
{
"userName": "name2",
"registered": true
}
]
How can I verify when userName = name1 then registered = false
When userName = name2 then registered = true
Tried something like this but it does not work.
.body("$.findAll{it.userinfo.userName = name1"}.registered", equalTo(false));
Did I miss something or do something wrong?
Here's something that can help you out,
String json = "{\r\n" + " \"userinfo\": [{\r\n" + " \"userName\": \"name1\",\r\n"
+ " \"registered\": false\r\n" + " },\r\n" + " {\r\n"
+ " \"userName\": \"name2\",\r\n" + " \"registered\": true\r\n" + " }\r\n"
+ " ]\r\n" + "}";
JsonPath js = new JsonPath(json);
String emp1Name = js.get("userinfo.find {it.userName == 'name2'}.registered").toString();
System.out.println(emp1Name);

3 levels Json how can I make a count inside

I want to consume an api that returns a json like this one:
{
"startDate": "2019-06-23T16:07:21.205Z",
"endDate": "2019-07-24T16:07:21.205Z",
"status": "Complete",
"usages": [
{
"name": "PureCloud Edge Virtual Usage",
"resources": [
{
"name": "Edge01-VM-GNS-DemoSite01 (1f279086-a6be-4a21-ab7a-2bb1ae703fa0)",
"date": "2019-07-24T09:00:28.034Z"
},
{
"name": "329ad5ae-e3a3-4371-9684-13dcb6542e11",
"date": "2019-07-24T09:00:28.034Z"
},
{
"name": "e5796741-bd63-4b8e-9837-4afb95bb0c09",
"date": "2019-07-24T09:00:28.034Z"
}
]
},
{
"name": "PureCloud for SmartVideo Add-On Concurrent",
"resources": [
{
"name": "jpizarro#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "jaguilera#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "dcortes#gns.com.co",
"date": "2019-07-15T15:06:09.203Z"
}
]
},
{
"name": "PureCloud 3 Concurrent User Usage",
"resources": [
{
"name": "jpizarro#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "jaguilera#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "dcortes#gns.com.co",
"date": "2019-07-15T15:06:09.203Z"
}
]
},
{
"name": "PureCloud Skype for Business WebSDK",
"resources": [
{
"name": "jpizarro#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "jaguilera#gns.com.co",
"date": "2019-06-25T04:54:17.662Z"
},
{
"name": "dcortes#gns.com.co",
"date": "2019-07-15T15:06:09.203Z"
}
]
}
],
"selfUri": "/api/v2/billing/reports/billableusage"
}
I have to count the amount of name in the last level. Looking on the web I´ve found a library and I just tried to adapt the example, but I have some doubts: one is that it starts with a string, not the route of the json file I have to test. I´ve put it in there manually, buy Eclipse added a lot of: /
When I try to run this:
String jsonString = "{\r\n" +
" \"startDate\": \"2019-06-23T16:07:21.205Z\",\r\n" +
" \"endDate\": \"2019-07-24T16:07:21.205Z\",\r\n" +
" \"status\": \"Complete\",\r\n" +
" \"usages\": [\r\n" +
" {\r\n" +
" \"name\": \"PureCloud Edge Virtual Usage\",\r\n" +
" \"resources\": [\r\n" +
" {\r\n" +
" \"name\": \"Edge01-VM-GNS-DemoSite01 (1f279086-a6be-4a21-ab7a-2bb1ae703fa0)\",\r\n" +
" \"date\": \"2019-07-24T09:00:28.034Z\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"329ad5ae-e3a3-4371-9684-13dcb6542e11\",\r\n" +
" \"date\": \"2019-07-24T09:00:28.034Z\"\r\n" +
" }, \r\n" +
" {\r\n" +
" \"name\": \"e5796741-bd63-4b8e-9837-4afb95bb0c09\",\r\n" +
" \"date\": \"2019-07-24T09:00:28.034Z\"\r\n" +
" }\r\n" +
" ]\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"PureCloud for SmartVideo Add-On Concurrent\",\r\n" +
" \"resources\": [\r\n" +
" {\r\n" +
" \"name\": \"jpizarro#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"jaguilera#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" }, \r\n" +
" {\r\n" +
" \"name\": \"dcortes#gns.com.co\",\r\n" +
" \"date\": \"2019-07-15T15:06:09.203Z\"\r\n" +
" }\r\n" +
" ]\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"PureCloud 3 Concurrent User Usage\",\r\n" +
" \"resources\": [\r\n" +
" {\r\n" +
" \"name\": \"jpizarro#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"jaguilera#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" }, \r\n" +
" {\r\n" +
" \"name\": \"dcortes#gns.com.co\",\r\n" +
" \"date\": \"2019-07-15T15:06:09.203Z\"\r\n" +
" }\r\n" +
" ]\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"PureCloud Skype for Business WebSDK\",\r\n" +
" \"resources\": [\r\n" +
" {\r\n" +
" \"name\": \"jpizarro#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"name\": \"jaguilera#gns.com.co\",\r\n" +
" \"date\": \"2019-06-25T04:54:17.662Z\"\r\n" +
" }, \r\n" +
" {\r\n" +
" \"name\": \"dcortes#gns.com.co\",\r\n" +
" \"date\": \"2019-07-15T15:06:09.203Z\"\r\n" +
" }\r\n" +
" ]\r\n" +
" }\r\n" +
" ],\r\n" +
" \"selfUri\": \"/api/v2/billing/reports/billableusage\"\r\n" +
"}\r\n" +
"";
int cantidadDeLicencias = 0;
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray usages = jsonObject.getJSONArray("usages");
System.out.println("usages " + usages);
for (int i = 0; i < usages.length(); i++) {
JSONArray resources = jsonObject.getJSONArray("resources");
for (int j = 0; j < resources.length(); j++) {
JSONArray names = jsonObject.getJSONArray("name");
cantidadDeLicencias = cantidadDeLicencias + names.length();
//String name = jsonObject.getJSONObject(j).getString("name");
}
}
System.out.println("Cantidad de licencias" + cantidadDeLicencias);
An error comes out: JSONObject["resources"] not found.
If the program would work, what changes I have to make cause, the api returns a json, you know, without all those: /. So this library is going to be useful?
Update
Now it works
int cantidadDeLicencias = 0;
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray usages = jsonObject.getJSONArray("usages");
System.out.println("usages " + usages);
for (int i = 0; i < usages.length(); i++) {
JSONObject innerTemp = usages.getJSONObject(i);
JSONArray resources = innerTemp.getJSONArray("resources");
//JSONArray resources = usages.getJSONArray("resources");
for (int j = 0; j < resources.length(); j++) {
String names = resources.getJSONObject(j).getString("name");
cantidadDeLicencias = cantidadDeLicencias + 1;
//String name = jsonObject.getJSONObject(j).getString("name");
}
}
System.out.println("Cantidad de licencias " + cantidadDeLicencias);
What should I do with the json? cause, here it has a lot of: / and the api doesn´t return that?
resources is inside a JSONObject, not directly inside the JSONArray.
Access it like this:
JSONArray usages = jsonObject.getJSONArray("usages");
for (int i = 0; i < usages.length(); i++) {
JSONObject innerTemp = usages.getJSONObject(i);
JSONArray resources = innerTemp.getJSONArray("resources");
// more code here
}

How to filter JSON Array

I have a dynamic JSON Array and I need to filter the JSON based on "isCalculatedField": false.
[{
"id": "CX.VOEFAIL.CREATEDT",
"description": "Task Management - Voe Fail Review Create Date",
"format": "STRING",
"maxLength": 40,
"modelPath": "Loan.CustomFields[(FieldName == 'CX.VOEFAIL.CREATEDT')].StringValue",
"isCalculatedField": false
},
{
"id": "CX.VOEFAIL.TASKCNT",
"description": "Task Management - VOE Fail Review Task Count",
"format": "INTEGER",
"maxLength": 0,
"modelPath": "Loan.CustomFields[(FieldName == 'CX.VOEFAIL.TASKCNT')].StringValue",
"isCalculatedField": false
},
{
"id": "CX.YEARS.AT.EMPLOYER",
"description": "Years employed",
"format": "DROPDOWNLIST",
"maxLength": 0,
"options": [
"Yes"
],
"modelPath": "Loan.CustomFields[(FieldName == 'CX.YEARS.AT.EMPLOYER')].StringValue",
"isCalculatedField": true
},
{
"id": "CX.YEARS.AT.RESIDENCE",
"description": "Years at residence",
"format": "DROPDOWNLIST",
"maxLength": 0,
"options": [
"Yes"
],
"modelPath": "Loan.CustomFields[(FieldName == 'CX.YEARS.AT.RESIDENCE')].StringValue",
"isCalculatedField": true
}]
How can I get sub JSON list containing "isCalculatedField" : false??
I have this JSON data in String.
Use JSON-P:
import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
public class Playground {
public static void main(String[] args) {
String json = "[{\n"
+ " \"id\": \"CX.VOEFAIL.CREATEDT\",\n"
+ " \"description\": \"Task Management - Voe Fail Review Create Date\",\n"
+ " \"format\": \"STRING\",\n"
+ " \"maxLength\": 40,\n"
+ " \"modelPath\": \"Loan.CustomFields[(FieldName == 'CX.VOEFAIL.CREATEDT')].StringValue\",\n"
+ " \"isCalculatedField\": false\n"
+ "},\n"
+ "{\n"
+ " \"id\": \"CX.VOEFAIL.TASKCNT\",\n"
+ " \"description\": \"Task Management - VOE Fail Review Task Count\",\n"
+ " \"format\": \"INTEGER\",\n"
+ " \"maxLength\": 0,\n"
+ " \"modelPath\": \"Loan.CustomFields[(FieldName == 'CX.VOEFAIL.TASKCNT')].StringValue\",\n"
+ " \"isCalculatedField\": false\n"
+ "},\n"
+ "{\n"
+ " \"id\": \"CX.YEARS.AT.EMPLOYER\",\n"
+ " \"description\": \"Years employed\",\n"
+ " \"format\": \"DROPDOWNLIST\",\n"
+ " \"maxLength\": 0,\n"
+ " \"options\": [\n"
+ " \"Yes\"\n"
+ " ],\n"
+ " \"modelPath\": \"Loan.CustomFields[(FieldName == 'CX.YEARS.AT.EMPLOYER')].StringValue\",\n"
+ " \"isCalculatedField\": true\n"
+ "},\n"
+ "{\n"
+ " \"id\": \"CX.YEARS.AT.RESIDENCE\",\n"
+ " \"description\": \"Years at residence\",\n"
+ " \"format\": \"DROPDOWNLIST\",\n"
+ " \"maxLength\": 0,\n"
+ " \"options\": [\n"
+ " \"Yes\"\n"
+ " ],\n"
+ " \"modelPath\": \"Loan.CustomFields[(FieldName == 'CX.YEARS.AT.RESIDENCE')].StringValue\",\n"
+ " \"isCalculatedField\": true\n"
+ "}]";
JsonReader reader = Json.createReader(new StringReader(json));
JsonArray array = reader.readArray();
for (int i = 0; i < array.size(); i++) {
JsonObject obj = array.getJsonObject(i);
if (!obj.getBoolean("isCalculatedField")) {
System.out.println(obj.toString() + " is not calculated");
}
}
}
}
Output:
{"id":"CX.VOEFAIL.CREATEDT","description":"Task Management - Voe Fail Review Create Date","format":"STRING","maxLength":40,"modelPath":"Loan.CustomFields[(FieldName == 'CX.VOEFAIL.CREATEDT')].StringValue","isCalculatedField":false} is not calculated
{"id":"CX.VOEFAIL.TASKCNT","description":"Task Management - VOE Fail Review Task Count","format":"INTEGER","maxLength":0,"modelPath":"Loan.CustomFields[(FieldName == 'CX.VOEFAIL.TASKCNT')].StringValue","isCalculatedField":false} is not calculated
You can use DSM library. By using it you can filter JSON while you reading JSON data.
You will define a YAML file that contains definitions of your mappings
Mapping File:
result:
type: array # result is array
path: /
filter: self.data.isCalculatedField # filter by isCalculatedField
fields:
id:
description:
modelPath:
isCalculatedField: boolean
format:
Use DSM to filter data.
DSM dsm=new DSMBuilder(new File("path/to/config.yaml")).create();
Object object=dsm.toObject(new File("path/to/data.json");
Here is the result:
[ {
"id" : "CX.YEARS.AT.EMPLOYER",
"description" : "Years employed",
"format" : "DROPDOWNLIST",
"modelPath" : "Loan.CustomFields[(FieldName == 'CX.YEARS.AT.EMPLOYER')].StringValue",
"isCalculatedField" : true
}, {
"id" : "CX.YEARS.AT.RESIDENCE",
"description" : "Years at residence",
"format" : "DROPDOWNLIST",
"modelPath" : "Loan.CustomFields[(FieldName == 'CX.YEARS.AT.RESIDENCE')].StringValue",
"isCalculatedField" : true
}, {
"id" : "CX.YEARS.AT.RESIDENCE",
"description" : "Years at residence",
"format" : "DROPDOWNLIST",
"modelPath" : "Loan.CustomFields[(FieldName == 'CX.YEARS.AT.RESIDENCE')].StringValue",
"isCalculatedField" : true
} ]

Json Response to string Array

I want to convert my json string to string array. My JSON string is having two parameters "href" and "name". I want to create List of string of values of "name" parameter using java. I am using NetBeans for my application. please help me out to resolve this issue. I am getting error as
Exception in thread "AWT-EventQueue-0" org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
JSONArray arr = new JSONArray(response);
List<String> list = new ArrayList<String>();
for(int i = 0; i < arr.length(); i++){
list.add(arr.getJSONObject(i).getString("name"));
System.out.println(arr.getJSONObject(i).getString("name"));
}
This is my JSON string
[
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/1",
"name": "analogValue_1"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/9",
"name": "analogValue_9"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/2",
"name": "analogValue_2"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/8",
"name": "analogValue_8"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/7",
"name": "analogValue_7"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/3",
"name": "analogValue_3"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/6",
"name": "analogValue_6"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/5",
"name": "analogValue_5"
},
{
"href": "\/api\/rest\/v1\/protocols\/bacnet\/local\/objects\/analog-value\/4",
"name": "analogValue_4"
}
]
Fix your json. 1. Change square brackets to curly brackets. 2. Each dictionary inside of your json is a value which must have a corresponding key. You code should look like this:
public static void main(String[] args) {
String myJSON = "{data_0:\n"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/1\",\n"
+ " \"name\": \"analogValue_1\"\n"
+ " },\n data_1:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/9\",\n"
+ " \"name\": \"analogValue_9\"\n"
+ " },\n data_2:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/2\",\n"
+ " \"name\": \"analogValue_2\"\n"
+ " },\n data_3:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/8\",\n"
+ " \"name\": \"analogValue_8\"\n"
+ " },\n data_4:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/7\",\n"
+ " \"name\": \"analogValue_7\"\n"
+ " },\n data_5:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/3\",\n"
+ " \"name\": \"analogValue_3\"\n"
+ " },\n data_6:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/6\",\n"
+ " \"name\": \"analogValue_6\"\n"
+ " },\n data_7:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/5\",\n"
+ " \"name\": \"analogValue_5\"\n"
+ " },\n data_8:"
+ " {\n"
+ " \"href\": \"\\/api\\/rest\\/v1\\/protocols\\/bacnet\\/local\\/objects\\/analog-value\\/4\",\n"
+ " \"name\": \"analogValue_4\"\n"
+ " }\n"
+ "}";
JSONObject jsonObject = new JSONObject(myJSON);
System.out.println("jsonObject: " + jsonObject.toString());
List<String> list = new ArrayList<String>();
System.out.println("jsonObject length: " + jsonObject.length());
for (int i = 0; i < jsonObject.length(); i++) {
list.add(jsonObject.getJSONObject("data_" + i).toString());
System.out.println(jsonObject.getJSONObject("data_" + i));
}
}
I added keys from data_0 to data_8. Then you create a list. Probably that does not exactly solve your problem, but least gives an idea where you're making a mistake.
From your comment we can see that you're using okhttp3.internal.http.RealResponseBody. Since the toString() method is not overwritten, the default implementation is used which is why System.out.println(response.body().toString()); prints okhttp3.internal.http.RealResponseBody#66cdc1bd.
To get the actual raw response use the string() method:
JSONArray arr = new JSONArray(responseBody.string());
According to the documentation (RealResponseBody extends ResponseBody):
String string()
Returns the response as a string decoded with the charset of the Content-Type header.
This also has already been discussed here by the way.

Categories