How to read specific json object element from the json array? [duplicate] - java

This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 3 years ago.
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
I want to read only the 'home' phone number not 'fax' phone number from the phoneNumbers json array. I don't want to use indexing to get the 'home' phone number.

If you do not want to use indexing you could filter phoneNumbers array by property. Using JSONArray, JSONObject classes and Java 8 streams:
String json = Files.lines(Paths.get("src/main/resources/data.json")).collect(Collectors.joining());
JSONObject jsonObject = new JSONObject(json);
JSONArray phoneNumbers = jsonObject.getJSONArray("phoneNumbers");
String homeNumber = phoneNumbers.toList()
.stream()
.map(o -> (Map<String, String>) o)
.filter(stringStringMap -> stringStringMap.get("type").equals("home"))
.map(stringStringMap-> stringStringMap.get("number"))
.findFirst()
.orElse("unknown");
System.out.println(homeNumber);
This prints:
212 555-1234

Related

Parsing a JSON array WITHOUT a wrapper class

I'm trying to parse a JSON array into a Java ArrayList using Gson.
{
"fathers": [
{
"name": "Donald",
"age": 47,
"children": [
{
"name": "Johnny",
"age": 6
},
{
"name": "Donna",
"age": 15
},
{
"name": "Alan",
"age": 21
}
]
},
{
"name": "George",
"age": 35,
"children": [
{
"name": "Cynthia",
"age": 10
},
{
"name": "Stacey",
"age": 5
},
{
"name": "Dewey",
"age": 2
}
]
}
]
}
I'm trying to parse the "fathers" array into an ArrayList... However, I can't do it directly, since the fathers array is wrapped by a JSON object. Normally, I would do something like this:
Type fathersListType = new TypeToken<ArrayList<Father>>(){}.getType();
fathersArrayList = gson.fromJson(fathersJson, fathersListType);
But, since the fathers array is wrapped by an object, I get this error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Is there a way to parse said array, without having to declare a wrapper class, that contains a "fathers" array? Like ignoring the wrapping object, or extracting the JSON array from it.
You can parse the root object as a Map:
Type rootType = new TypeToken<Map<String, List<Person>>>(){}.getType();
Map<String, List<Person>> root = gson.fromJson(fathersJson, rootType);
List<Person> fathersList = root.get("fathers");
Something like this should work:
String data = "{...}"; // Your JSON
JsonArray array = new JsonParser().parse(data).getAsJsonObject().get("fathers").getAsJsonArray();
List<Father> fathers = Arrays.asList(new Gson().fromJson(array, Father[].class));
Arrays.asList comes from https://commons.apache.org/

How to parse JSON nested arrays [duplicate]

This question already has answers here:
How do I parse JSON in Android? [duplicate]
(3 answers)
Closed 5 years ago.
"sport_events": [
{
"id": "sr:match:12606716",
"scheduled": "2017-09-27T10:00:00+00:00",
"start_time_tbd": false,
"status": "closed",
"tournament_round": {
"type": "group",
"number": 1,
"group": "Gr. 4"
},
"season": {
"id": "sr:season:45960",
"name": "U17 European Ch.ship QF 17/18",
"start_date": "2017-09-27",
"end_date": "2018-04-30",
"year": "17/18",
"tournament_id": "sr:tournament:755"
},
"tournament": {
"id": "sr:tournament:755",
"name": "U17 European Ch.ship QF",
"sport": {
"id": "sr:sport:1",
"name": "Soccer"
},
"category": {
"id": "sr:category:392",
"name": "International Youth"
}
},
"competitors": [
{
"id": "sr:competitor:22646",
"name": "Russia",
"country": "Russia",
"country_code": "RUS",
"abbreviation": "RUS",
"qualifier": "home"
},
{
"id": "sr:competitor:22601",
"name": "Faroe Islands",
"country": "Faroe Islands",
"country_code": "FRO",
"abbreviation": "FRO",
"qualifier": "away"
}
]
},
Add gson to your project by adding this into your build-script.gradle:
dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}
Now create the classes you need but first correct your json string. I guess you forgot a attributename at the beginning. This is your new best friend: json formatter online
After you corrected your json-string and you´ve created your Wrapper and Pojo model-classes with the needed attributes, you parse the string back into the wrapper-object and with getter/setter you get change/get data out of it.
Gson gson = new GsonBuilder().create();
Wrapper wrap = gson.fromJson(jsonString, Wrapper.class);
Don´t forget try-catch block because there can be many thrown exceptions.
Good luck to you.
How-to-for-beginner

JSON object not found in JSON array

I am aware there are duplicate questions. I am not able to figure this out despite that.
Below is a JSON file which I receive from an API. I need to get the "year" value.
The error I am getting is:
message org.glassfish.jersey.server.ContainerException: org.json.JSONException: JSONArray[1] not found.
Which relates to the line on Java:
JSONObject year = years.getJSONObject(1).getJSONObject("years");
I also tried:
JSONObject year = years.getJSONObject(1);
Why is this code not working? Isn't index 1 clearly year in the years array?
JSON
{
"make": {
"id": 200000404,
"name": "Chevrolet",
"niceName": "chevrolet"
},
"model": {
"id": "Chevrolet_Camaro",
"name": "Camaro",
"niceName": "camaro"
},
"drivenWheels": "rear wheel drive",
"numOfDoors": "2",
"options": [],
"colors": [],
"manufacturerCode": "1EH67",
"price": {
"baseMSRP": 34180.0,
"baseInvoice": 32813.0,
"deliveryCharges": 900.0,
"usedTmvRetail": 17766.0,
"usedPrivateParty": 16321.0,
"usedTradeIn": 14755.0,
"estimateTmv": false,
"tmvRecommendedRating": 0
},
"categories": {
"market": "Performance",
"EPAClass": "Compact Cars",
"vehicleSize": "Midsize",
"primaryBodyType": "Car",
"vehicleStyle": "Convertible",
"vehicleType": "Car"
},
"vin": "2G1FC3D33C9165616",
"squishVin": "2G1FC3D3C9",
"years": [{
"id": 100531911,
"year": 2012,
"styles": [{
"id": 101395591,
"name": "LT 2dr Convertible w/2LT (3.6L 6cyl 6M)",
"submodel": {
"body": "Convertible",
"modelName": "Camaro Convertible",
"niceName": "convertible"
},
"trim": "LT"
}]
}],
"matchingType": "SQUISHVIN",
"MPG": {
"highway": "28",
"city": "17"
}
}
JAVA
public String vehicleData(#PathParam("vin") String vin,
#PathParam("key") String key) throws Exception {
GetVehicleJSON jsonData = new GetVehicleJSON(vin, key);
JSONObject data = jsonData.getVehicleData();
String name = data.getJSONObject("make").getString("name");
String highway = data.getJSONObject("MPG").getString("highway");
String city = data.getJSONObject("MPG").getString("city");
JSONArray years = data.getJSONArray("years");
JSONObject year = years.getJSONObject(1).getJSONObject("years");
String s = year.getString("year");
return name + " " + s + " " + highway + " " + city;
}
You're working with JSON array whose indexing is zero-based. Do it as:
JSONArray years = data.getJSONArray("years");
String year = years.getJSONObject(0).getString("year");
Your json shows that the years value is an array with 1 element and inside that element is an object:
"years": [{ "id": 100531911, "year": 2012, "styles": [{ "id": 101395591, "name": "LT 2dr Convertible w/2LT (3.6L 6cyl 6M)", "submodel": { "body": "Convertible", "modelName": "Camaro Convertible", "niceName": "convertible" }, "trim": "LT" }] }],
Because array element numbering begins at 0, that means if you select element 1 you will get this error:
message org.glassfish.jersey.server.ContainerException: org.json.JSONException: JSONArray[1] not found.
To fix it you need to select element 0 instead of 1:
years.getJSONObject(0);

Java: Merging two json objects together with primary key

Lets say I have two arrays of JSONObjects in memory and each object has a key that is similar in both arrays:
Array 1
[
{
"name": "Big Melons Co.",
"location": "Inner City Dubai"
"id": "1A"
},
{
"name": "Pear Flavored Juices Ltd",
"location": "Seychelles"
"id": "2A"
},
{
"name": "Squeeze My Lemons LLC",
"location": "UK"
"id": "3A"
}, {other JSON Objects...} ]
Array 2
[
{
"acceptsCard": "true"
"id": "1A"
},
{
"acceptsCard": "false"
"id": "2A"
},
{
"acceptsCard": "false"
"id": "3A"
}, {other JSON Objects...} ]
Now, I want to merge the two arrays together based on the primary key of "id" so they become one on my server side and then send the results back to my frontend - the resulting arraylist of objects should look like this:
MERGED ARRAY (Result)
[
{
"name": "Great Juice Co.",
"location": "Inner City Dubai"
"acceptsCard": "true"
"id": "1A"
},
{
"name": "Pear Flavored Juices Ltd",
"location": "Seychelles"
"acceptsCard": "false"
"id": "2A"
},
{
"name": "Squeeze My Lemons LLC",
"location": "UK"
"acceptsCard": "false"
"id": "3A"
}, {other JSON Objects...} ]
How can I do this efficiently?
I can think of one highly inefficient way to do this (I'm dreading implementing this) - I would loop though each item in either array 1 or 2 and use the equal() method for the string in the "id" field to see whether the two matches. If they match, I would create a new JSONObject to contain both the fields from array 1 and 2.
My Java is a little rusty but I would use a map.
List<JSONObject> objectsA = ... ;
List<JSONObject> objectsB = ... ;
Map entries = new HashMap<String, JSONObject>();
List<JSONObject> allObjects = new ArrayList<JSONObject>();
allObjects.addAll(objectsA);
allObjects.addAll(objectsB);
for (JSONObject obj: allObjects) {
String key = obj.getString("id");
JSONObject existing = entries.get(key);
if (existing == null) {
existing = new JSONObject();
entries.put(key, existing);
}
for (String subKey : obj.keys()) {
existing.put(subKey, obj.get(subKey));
}
}
List<JSONObject> merged = entries.values();
This is more efficient than two nested loops and there's still room for improvement.
EDIT: References to external documentation and related answers.
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
http://www.json.org/javadoc/org/json/JSONObject.html
https://stackoverflow.com/a/2403427/937006

Parse JSON with org.json [duplicate]

This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 5 years ago.
I'm trying to parse an output from a server that looks like this:
{
"GetFolderFilesByZoneResult": [
{
"ID": 98748,
"CreatedBy": "",
"UpdatedBy": "none",
"CreatedDate": "\/Date(1308273033620+0100)\/",
"UpdatedDate": "\/Date(1308303003770+0100)\/",
"CommentCount": 0,
"Key": "",
"Enabled": true,
"MimeType": "video",
"Votes": 2,
"TotalRating": 0,
"AllowComments": true,
"ViewCount": 323,
"ReleaseDate": "\/Date(1308273000000+0100)\/",
"ExpireDate": "\/Date(4102444800000+0000)\/",
"Author": "",
"Size": 133799936,
"Tag1": "",
"Tag2": "",
"Tag3": "",
"RecycleBin": false
},
{
"ID": 99107,
"CreatedBy": "",
"UpdatedBy": "none",
"CreatedDate": "\/Date(1308583412520+0100)\/",
"UpdatedDate": "\/Date(1308583564007+0100)\/",
"CommentCount": 0,
"Key": "",
"Enabled": true,
"MimeType": "video",
"Votes": 0,
"TotalRating": 0,
"AllowComments": true,
"ViewCount": 33,
"ReleaseDate": "\/Date(1308583380000+0100)\/",
"ExpireDate": "\/Date(4102444800000+0000)\/",
"Author": "",
"Size": 47955968,
"Tag1": "",
"Tag2": "",
"Tag3": "",
"RecycleBin": false
}
]
}
I'm trying to use Java org.json to parse it, but I don't have any experience with JSON/org.json, so I'm having a little trouble. How can I parse this?
1) Assuming you have the JSON libraries on your path (from www.json.org), it's pretty easy.
import org.json.JSONTokener;
...
URI uri = new URI("http://someserver/data.json");
JSONTokener tokener = new JSONTokener(uri.toURL().openStream());
JSONObject root = new JSONObject(tokener);
From there, you can address the various parts of the JSON object. Take a look at the Javadocs for the specifics.
https://developer.android.com/reference/org/json/package-summary.html
Here is the most universal solution, which allows to parse any JSON type into appropriate Java type:
Object json = new JSONTokener(response).nextValue();
Then you can determine resulting type and handle it appropriately.
I'd pass it
map<String, Object>
loaded with
map<String, Object>
in the object field.
Basically recreating the hierarchy of your java classes inside of a large map.
Example :
return ( Map<"GetFolderFilesByZoneResult", Map<"Result1", (object by id 98748) | "Result2", (object by id 99107) | "Result3", etc.
JSON will return that big map very pretty like, and programmatically it's easier to do then lists.

Categories

Resources