Get Nested JSONObject Java? - java

I am trying to get a JSON object nested inside another JSON object. When I run my main class:
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException, JSONException {
NBAPlayers players = new NBAPlayers();
JSONObject json = players.readJsonFromUrl("http://data.nba.net/10s/prod/v1/2017/players.json");
JSONObject League = json.getJSONObject("league");
JSONObject standard =League.getJSONObject("standard");
JSONObject firstName = standard.getJSONObject("firstName");
}
}
I get the error:
Exception in thread "main" org.json.JSONException:
JSONObject["standard"] is not a JSONObject.
I am using the the maven artifact org.json:json package.

This is a part of json that returns url in the example
{
"_internal": {
"pubDateTime": "2017-12-10 11:42:23.504",
"xslt": "xsl/league/roster/marty_active_players.xsl",
"eventName": "league_roster"
},
"league": {
"standard": [
{
"firstName": "Alex",
"lastName": "Abrines",
"personId": "203518",
"teamId": "1610612760",
"jersey": "8",
"isActive": true,
"pos": "G",
"heightFeet": "6",
"heightInches": "6",
"heightMeters": "1.98",
"weightPounds": "190",
"weightKilograms": "86.2",
"dateOfBirthUTC": "1993-08-01",
"teams": [
{
"teamId": "1610612760",
"seasonStart": "2016",
"seasonEnd": "2017"
}
],
"draft": {
"teamId": "1610612760",
"pickNum": "32",
"roundNum": "2",
"seasonYear": "2013"
},
"nbaDebutYear": "2016",
"yearsPro": "1",
"collegeName": "",
"lastAffiliation": "Spain/Spain",
"country": "Spain"
},
{
"firstName": "Quincy",
"lastName": "Acy",
"personId": "203112",
"teamId": "1610612751",
"jersey": "13",
"isActive": true,
"pos": "F",
"heightFeet": "6",
"heightInches": "7",
"heightMeters": "2.01",
"weightPounds": "240",
"weightKilograms": "108.9",
"dateOfBirthUTC": "1990-10-06",
"teams": [
{
"teamId": "1610612761",
"seasonStart": "2012",
"seasonEnd": "2013"
},
{
"teamId": "1610612758",
"seasonStart": "2013",
"seasonEnd": "2013"
},
{
"teamId": "1610612752",
"seasonStart": "2014",
"seasonEnd": "2014"
},
{
"teamId": "1610612758",
"seasonStart": "2015",
"seasonEnd": "2015"
},
{
"teamId": "1610612742",
"seasonStart": "2016",
"seasonEnd": "2016"
},
{
"teamId": "1610612751",
"seasonStart": "2016",
"seasonEnd": "2017"
}
],
as you can see standard is not an object. It is array.
You should change your code as follows
JSONArray standard =League.getJSONArray("standard");
for (int i = 0; i < standard.length(); i++) {
String firstName = standard.getJSONObject(i).getString("firstName");
}

Related

Grouping JSON output by an attribute

I have a source JSON string I would like to convert into local-attributed JSON. I'm trying to achieve:
{
"dep": 1552928400000,
"des": "USA",
"listWagonDetail": [
{
"listSeatDetail": [
{
"seatColumn": "A",
"seatRow": "1",
"seatStatus": "1",
"subclass": "C"
},
{
"seatColumn": "A",
"seatRow": "2",
"seatStatus": "0",
"subclass": "C"
},
{
"seatColumn": "A",
"seatRow": "3",
"seatStatus": "1",
"subclass": "C"
}
],
"numSeat": 0,
"wagonCode": "PRE",
"wagonNo": "1"
},
{
"listSeatDetail": [
{
"seatColumn": "A",
"seatRow": "1",
"seatStatus": "0",
"subclass": "C"
},
{
"seatColumn": "A",
"seatRow": "2",
"seatStatus": "0",
"subclass": "C"
},
{
"seatColumn": "A",
"seatRow": "3",
"seatStatus": "1",
"subclass": "C"
}
],
"numSeat": 0,
"wagonCode": "PRE",
"wagonNo": "2"
}
],
"numWagon": 0,
"org": "AU",
"subClass": null,
"trainNo": "77"
}
Which is to group each listSeatDetail by WagonNo. But instead I got this on my work where "numSeat", "wagonCode" and "WagonNo" is looped every listSeatDetail and only the last data of each array are shown:
{
"dep": 1552928400000,
"des": "USA",
"listWagonDetail": [
{
"listSeatDetail": [
{
"seatColumn": "A",
"seatRow": "3",
"seatStatus": "1",
"subclass": "C"
}
],
"numSeat": 0,
"wagonCode": "PRE",
"wagonNo": "2"
},
{
"listSeatDetail": [
{
"seatColumn": "A",
"seatRow": "3",
"seatStatus": "1",
"subclass": "C"
}
],
"numSeat": 0,
"wagonCode": "PRE",
"wagonNo": "2"
},
{
"listSeatDetail": [
{
"seatColumn": "A",
"seatRow": "3",
"seatStatus": "1",
"subclass": "C"
}
],
"numSeat": 0,
"wagonCode": "PRE",
"wagonNo": "2"
},
How can I achieve the first JSON? Here is part of my code:
private void generateSeat(GetSeatRequest request, GetSeatMapResponse seatMapResponse,
SeatMapResponsePojo seatmapResponsePojo) {
seatMapResponse.setDepDate(request.getDepDate());
seatMapResponse.setDes(request.getDes());
seatMapResponse.setOrg(request.getOrg());
seatMapResponse.setTrainNo(request.getTrainNo());
seatMapResponse.setNumWagon(0);
seatMapResponse.setSubClass(request.getSubClass());
List<WagonDetail> listWagonDetail = new ArrayList<>();
for (SeatMapPojo seatmap : seatmapResponsePojo.getPayload()) {
WagonDetail wagon = new WagonDetail();
String wagonNoString = seatmap.getStamformdetcode();
String[] wagonNo = wagonNoString.split("-");
for (WagonDetail wagondetail : listWagonDetail) {
wagondetail.setNumSeat(0);
wagondetail.setWagonCode(wagonNo[0]);
wagondetail.setWagonNo(wagonNo[1]);
List<SeatDetail> listSeatDetail = new ArrayList<>();
SeatDetail seatDetail = new SeatDetail();
seatDetail.setSeatColumn(seatmap.getWagondetcol());
seatDetail.setSeatRow(seatmap.getWagondetrow());
seatDetail.setSeatStatus(seatmap.isIsavilable() ? "0" : "1");
seatDetail.setSubclass(seatmap.getSubclass());
listSeatDetail.add(seatDetail);
wagondetail.setListSeatDetail(listSeatDetail);
}
listWagonDetail.add(wagon);
}
seatMapResponse.setListWagonDetail(listWagonDetail);
}
I'd recommend you to use google Gson, which is the best serialize/deserialize Library of JSON so far we found.
which you could define the desired class like this:
class Output{
private int depDate;
private String des;
...
private List<WagonDetail> listWagonDetail;
//... getter()/setter()
}
then you could define WagonDetail:
class WagonDetail{
private List<SeatDetail> listSeatDetail;
private int numSeat;
....
}
then class SeatDetail so on
And you could use gson to serialize that class Output pretty easily:
Output output = new Output();
//set according attributes using setter/getter
Gson gson = new Gson();
String jsStr = gson.toJson(output);
Deserialize the JSON string to an object is easily too:
String jsStr = "..."
Gson gson = new Gson();
Output output = gson.fromJson(jsStr, Output.class);

Add new attribute in JSONArray

I have the following scenario
"sections": [
{
"id": XXXX,
"tipology": "TIPOLOGY"
},
{
"id": XXXX,
"tipology": "TIPOLOGY"
},
{"num": 2}
],
I'm using JSONArray and JSONObject. Is there some way to do this?
"sections": [
"num": 2,
{
"id": XXXX,
"tipology": "TIPOLOGY"
},
{
"id": XXXX,
"tipology": "TIPOLOGY"
},
],
I believe you are trying to count the array within. I think you can do it below way.
{
"sections": [{
"id": "XXXX",
"tipology": "TIPOLOGY"
},
{
"id": "XXXX",
"tipology": "TIPOLOGY"
}
],
"num": 2
}
OR
{
"sections": [{
"id": "XXXX",
"tipology": "TIPOLOGY"
},
{
"id": "XXXX",
"tipology": "TIPOLOGY"
}, {
"id": "COUNT",
"num": 2
}
]
}
You can have the json object in the following format, hope it works for you.
{
"sections": {
"num": 100,
"values": [{
"id": "XXXX",
"tipology": "TIPOLOGY"
}]
}
}
And the java code for the above program is below.
import org.json.*;
class test {
public static void main(String[] args) throws JSONException {
JSONObject sections = new JSONObject();
JSONObject obj = new JSONObject();
obj.put("num", new Integer(2));
JSONArray array = new JSONArray();
JSONObject value = new JSONObject();
value.put("id", "XXXX");
value.put("tipology", "TIPOLOGY");
array.put(value);
obj.put("values", array);
sections.put("sections", obj);
System.out.print(sections);
}
}

Why does REST API response contain the bean name?

I need a response like:
[
{
"id": 1,
"site": "Google",
"name": "abc",
"value": "111",
"level": "BASE",
"character": "&"
},
{
"id": 2,
"site": "Yahoo",
"name": "xyz",
"value": "222",
"level": "ONE",
"character": ";"
}
]
Instead, this is the response I get:
{
"responseObjects": [
[
{
"id": 1,
"site": "Google",
"name": "abc",
"value": "111",
"level": "BASE",
"character": "&"
},
{
"id": 2,
"site": "Yahoo",
"name": "xyz",
"value": "222",
"level": "ONE",
"character": ";"
}
]
]
}
My Response class has the following member:
private final List<Object> responseObjects = new ArrayList<Object>();
public List<Object> getResponseObjects() {
return responseObjects;
}
public void addToResponseObjects(Object responseObject) {
responseObjects.add(responseObject);
}
And in my Resource class I have this code that returns the response:
List<MyBean> responseList = new ArrayList<MyBean>();
.....
.....
.....
response.addToResponseObjects(responseList);
return response;
What changes would I need to do to not have "responseObjects" get added in the response? I only need to have the JSON String/Array in the response.

Parsing JSON using GSON with multiple inner objects.

I would like to parse the following JSON response, using GSON. As you can see, there are a lot of inner json objects in the response. Do I need to create POJO classes for all the inner objects or is there any alternative?
{
"nodeProperties": [
{
"properties": {
"timeStamp": {
"value": 1400475483694,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:03"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"tier": {
"value": 1
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "NEXT_NEWSwitch3"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:03",
"type": "OF"
}
},
{
"properties": {
"timeStamp": {
"value": 1400475481261,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:02"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"tier": {
"value": 1
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "None"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:02",
"type": "OF"
}
},
{
"properties": {
"timeStamp": {
"value": 1400475478695,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:01"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "None"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:01",
"type": "OF"
}
}
]
}
Simply convert the JSON string into Map.
Sample code:
FileReader in = new FileReader(new File("resources/json3.txt"));
BufferedReader br = new BufferedReader(in);
// Convert JSON string into MAP object
Gson gson = new Gson();
Type type = new TypeToken<Map<String, ArrayList<Map<String, Map<String, Object>>>>>() {}.getType();
Map<String, ArrayList<Map<String, Map<String, Object>>>> map = gson.fromJson(br, type);
for (String key : map.keySet()) {
System.out.println(key);
for (Map<String, Map<String, Object>> value : map.get(key)) {
for (String k : value.keySet()) {
System.out.println(k);
for (String k1 : value.get(k).keySet()) {
System.out.println(k1 + ":" + value.get(k).get(k1));
}
}
System.out.println("--------------");
}
}
in.close();
br.close();
You can do it using some POJO classes as well which are replica of the JSON string that is more simple and shorter.
Sample code:
class PropertiesNode {
Properties properties;
Node node;
// getter & setter
}
class Node {
String id;
String type;
// getter & setter
}
class Properties {
Map<String, Object> timeStamp;
Map<String, String> macAddress;
Map<String, Integer> tables;
Map<String, Integer> capabilities;
Map<String, Integer> tier;
Map<String, String> supportedFlowActions;
Map<String, Integer> buffers;
Map<String, String> description;
Map<String, Integer> forwarding;
// getter & setter
}
Gson gson = new Gson();
Type type = new TypeToken<Map<String, ArrayList<PropertiesNode>>>() {}.getType();
Map<String, ArrayList<PropertiesNode>> nodeProperties = gson.fromJson(br, type);
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(nodeProperties).toString());
output:
{
"nodeProperties": [
{
"properties": {
"timeStamp": {
"value": 1.400475483694E12,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:03"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"tier": {
"value": 1
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "NEXT_NEWSwitch3"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:03",
"type": "OF"
}
},
{
"properties": {
"timeStamp": {
"value": 1.400475481261E12,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:02"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"tier": {
"value": 1
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "None"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:02",
"type": "OF"
}
},
{
"properties": {
"timeStamp": {
"value": 1.400475478695E12,
"name": "connectedSince"
},
"macAddress": {
"value": "00:00:00:00:00:01"
},
"tables": {
"value": -1
},
"capabilities": {
"value": 199
},
"supportedFlowActions": {
"value": "[Controller, Drop, Enqueue, HwPath, Output, PopVlan, SetDlDst, SetDlSrc, SetNwDst, SetNwSrc, SetNwTos, SetTpDst, SetTpSrc, SetVlanId, SetVlanPcp, SwPath]"
},
"buffers": {
"value": 256
},
"description": {
"value": "None"
},
"forwarding": {
"value": 0
}
},
"node": {
"id": "00:00:00:00:00:00:00:01",
"type": "OF"
}
}
]
}

Json Format error, ask for array when he already gets one

I have a small issues when I try to parse the below JSON arrays
{
"category": [
{
"id": "1",
"idRef": "1",
"name": "projet",
"products": [
{
"category": "1",
"content": "produit du projet , et sa description",
"id": "5",
"name": "ProdProj",
"price": "10000.0"
},
{
"category": "1",
"content": "application de pokemon potoo",
"id": "7",
"name": "pokedex",
"price": "10000.0"
},
{
"category": "1",
"content": "description du projet n2",
"id": "8",
"name": "projet2",
"price": "100.0"
},
{
"category": "1",
"content": "Construisez de vos reve",
"id": "9",
"name": "Pokedex Dream",
"price": "100.0"
}
]
},
{
"id": "2",
"idRef": "2",
"name": "jeux video",
"products": [
{
"category": "2",
"content": "Description du projet de de tout ce qui suit",
"id": "6",
"name": "Jeux video Project",
"price": "10000.0"
},
{
"category": "2",
"content": "The description pokedex is relouu",
"id": "10",
"name": "thePokedex",
"price": "100.0"
}
]
},
{
"id": "3",
"idRef": "3",
"name": "apps mobil",
"products": [
{
"category": "3",
"content": "description de l'application numéro2",
"id": "11",
"name": "application2",
"price": "100.0"
},
{
"category": "3",
"content": "azerazeraze mobil",
"id": "12",
"name": "azerMobil",
"price": "100.0"
}
]
}
]
}
with this code:
public class GsonFormatter {
private static Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserDeserializer())
.registerTypeAdapter(Category.class, new CategoryDeserializer())
.registerTypeAdapter(Project.class, new ProjectDeserializer())
.create();
public static Gson getGson() {
return gson;
}
}
And I have this method that makes an error:
"Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2"
Public ArrayList<Category>() {
return GsonFormatter.getGson().fromJson(json,
new TypeToken<List<Category>>() {}.getType());
So I have been trying all night long. But I cannot figure out what is going wrong. This is my first JSON use, so i'm sorry for this stupid question...
The error is telling you that while parsing the JSON and mapping it to your Category class, there was a case where your class is expecting an object, but the JSON is an array.
Looking at your JSON, it's easy to see where that is. You have an array of Category objects. In one of them, products is an object, and in another it's an array:
... \"products\":[{\"category\":\"1\",\"content\":\"Jeux ...
... \"products\":{\"category\":\"3\",\"content\":\"application ...
Edit in response to comments: IMHO, yes, the way the server is producing the JSON is broken. What it appears is that if there is only one product in a category, it returns the single product as an object, but if there are multiple products you get an array of them. Ideally you would want the server to always return an array even when there's only one product.
If you can't get the server changed, what you would need to do is handle this in your deserializer. You'd have to manually check the products field and see if it's an object and convert it to an array for your class.
Your above-mentioned method only apples for get a json array without attributes to be extracted.
My following method is suggested to take a json object with an array associated with.
Gson gson = new Gson();
String jsonOutput = "{ \"array\": [{ \"id\" : \"3\", \"name\" : \"hello_world\" }, { \"id\" : \"2\", \"name\" : \"hello_world\" }] }";
JsonObject root = new JsonParser().parse(jsonOutput).getAsJsonObject();
JsonArray terms = root.getAsJsonArray("array");
//JSONArray cms = jsonObject.getJSONArray("array");
MyModel[] arr = gson.fromJson(terms.toString(), MyModel[].class);

Categories