com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
This is the error I continue to get while attempting to parse my incoming JSON response data. I'm utilizing the OkHttp library to create and call, and the API I'm getting results from returns everything in an Array as follows:
[
{
"id": 4256,
"image_url": "https://cdn.pandascore.co/images/league/image/4256/OMEN_Challenger_Series_2019.png",
"live_supported": false,
"modified_at": "2019-10-30T10:02:42Z",
"name": "OMEN Challenger",
"series": [
{
"begin_at": "2019-11-01T03:30:00Z",
"description": null,
"end_at": null,
"full_name": "2019",
"id": 1932,
"league_id": 4256,
"modified_at": "2019-10-30T09:11:40Z",
"name": null,
"prizepool": "50000 United States Dollar",
"season": null,
"slug": "cs-go-omen-challenger-2019",
"winner_id": null,
"winner_type": null,
"year": 2019
}
],
"slug": "cs-go-omen-challenger",
"url": "https://omengaming.co/omen_cs/",
"videogame": {
"current_version": null,
"id": 3,
"name": "CS:GO",
"slug": "cs-go"
}
},
{...},
{...},
{...},
{...},
]
I found a lot of folks recommending Gson to parse it into a custom class, but the following code, in theory, should work and it isn't. The parsing doesn't even begin due to it expecting BEGIN_OBJECT and it being BEGIN_ARRAY:
String jsonData = response.body().string();
Gson gson = new Gson();
EventInfo test = gson.fromJson(jsonData, EventInfo.class);
class EventInfo {
String imageURL;
String name;
JSONArray series;
}
You are trying to parse it into an object. But in your response, you can clearly see that it's a list. The parent POJO should have been a list. And inside that list, you should have created another POJO.
In your response parent is found as array but you need to add first parent as JSON object and child as a array or object.
You need response like this
{
"YourArrayName":[
"YourChildObjName":{
"id": 4256,
"image_url": "https://cdn.pandascore.co/images/league/image/4256/OMEN_Challenger_Series_2019.png",
"live_supported": false,
"modified_at": "2019-10-30T10:02:42Z",
"name": "OMEN Challenger",
"series": [
{
"begin_at": "2019-11-01T03:30:00Z",
"description": null,
"end_at": null,
"full_name": "2019",
"id": 1932,
"league_id": 4256,
"modified_at": "2019-10-30T09:11:40Z",
"name": null,
"prizepool": "50000 United States Dollar",
"season": null,
"slug": "cs-go-omen-challenger-2019",
"winner_id": null,
"winner_type": null,
"year": 2019
}
],
"slug": "cs-go-omen-challenger",
"url": "https://omengaming.co/omen_cs/",
"videogame": {
"current_version": null,
"id": 3,
"name": "CS:GO",
"slug": "cs-go"
}
},
{...},
{...},
{...},
{...},
]
}
I hope this can help You!
Thank You
So, I figured it out. Originally I was receiving the same error at a later point; namely when it got to the series key value in the first JSONObject. The original error occurred because I was trying to parse series as a JSONArray, rather than a List<JSONObject> The corrections are below:
String jsonData = response.body().string();
Gson gson = new Gson();
Type listType = new TypeToken<List<EventInfo>>() {}.getType();
List<EventInfo> test = gson.fromJson(jsonData, listType);
And the EventInfo class:
class EventInfo {
String imageURL;
String name;
List<JSONObject> series;
}
Thank you for the advice everyone!
Related
I am obtaining a JSON response from an API that gives me a list of call records formatted as JSON. I want to parse through the data and find the record ID, my trouble is that each JSON record has multiple ID's and I am not sure how to access the correct one. Keep in mind, I do not know the value of the ID is "3461487000073355176" prior to running the request.
This is my code to receive the JSON, I created a JSONObject so I can hopefully store the value.
1.
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser parser = new JsonParser();
JsonElement je = parser.parse(responseBody);
String prettyJsonString = gson.toJson(je);
JSONObject json = new JSONObject(prettyJsonString);
System.out.println("Json = " + json);
The JSON the ID I need to access has a comment next to it:
"data": [
{
"Owner": {
"name": "My namen",
"id": "346148700000017",
"email": "m#gmail.com"
},
"$state": "save",
"$process_flow": false,
"Street": "95## ### ######",
"id": "**3461487000073355176**", ----This is the ID I need -----
"Coverage_A_Dwelling": 100000,
"$approval": {
"delegate": false,
"approve": false,
"reject": false,
"resubmit": false
},
"Created_Time": "2020-12-10T09:05:17-05:00",
"Property_Details": "Primary Residence",
"Created_By": {
"name": "My name",
"id": "346148700000017",
"email": "m#gmail.com"
},
"Description": "Created on Jangl: https://jan.gl/crwp773ytg8",
"$review_process": {
"approve": false,
"reject": false,
"resubmit": false
},
"Property_State": "FL",
"Property_Street": "95",
"Roof_Material": "Asphalt Shingle",
"Full_Name": "Clare Em",
"Property_City": "Land ",
"Email_Opt_Out": false,
"Lead_I_D": "4FFEC0C5-FBA1-2463-DB9B-C38",
"Insured_1_DOB": "1942-02-20",
"$orchestration": false,
"Tag": [],
"Email": "cr#yahoo.com",
"$currency_symbol": "$",
"$converted": false,
"Zip_Code": "338",
"$approved": true,
"$editable": true,
"City": "Land O Lakes",
"State": "FL",
"Structure_Type": "Single Family",
"Prior_Carrier": {
"name": "Default Carrier (DO NOT DELETE OR CHANGE)",
"id": "3461487000000235093"
},
"Source": {
"name": "EverQ",
"id": "346148700006474"
},
"First_Name": "Clarence",
"Modified_By": {
"name": "My name",
"id": "3461487000000172021",
"email": "m#gmail.com"
},
"Phone": "7036159075",
"Modified_Time": "2020-12-10T09:05:17-05:00",
"$converted_detail": {},
"Last_Name": "####",
"$in_merge": false,
"$approval_state": "approved",
"Property_Zip": "34638"
}
],
"info": {
"per_page": 200,
"count": 1,
"page": 1,
"more_records": false
}
}
If I understood it correctly, you can get the id like this:
Here, json has the following value.
[
{
"Owner": {
"name": "My namen",
"id": "346148700000017",
"email": "m#gmail.com"
},
"id": "**3461487000073355176**"
...
}
]
Now I can iterate over JSONArray to get the id.
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = (JSONObject) jsonArray.get(i);
String id = (String) jsonObject.get("id");
System.out.println(id);
}
It prints out **3461487000073355176**.
You can do jsonObject.getJSONArray("data"); in your example to obtain JSON array.
The posted JSON response is missing the initial "{".
Your JSON contains data, which is a JSONArray of Owner objects. To get the id field of the first owner (array element 0):
// existing code
JSONObject json = new JSONObject(prettyJsonString);
System.out.println("Json = " + json);
// get the id field
JSONArray dataArray = (JSONArray)json.get("data");
JSONObject data0 = (JSONObject) dataArray.get(0);
JSONObject owner = (JSONObject) data0.get("Owner");
String id = owner.getString("id");
System.out.println(id);
Not sure if understood correctly but if you need to get all the IDs in that "level" why don't you try to model it as a class instead of using parser and let Gson do the parsing (this class might be useful later if you need to add more details)?
For example, defining something like this:
#Getter #Setter
// This models the response string from body
public class Response {
#Getter #Setter
// This models objects in the data list/array
public static class IdHolder {
// Only id because not interested of the rest
private String id;
}
// Only list of id holders because not interested of the rest
private List<IdHolder> data;
}
Then it would be as easy as:
Response res = gson.fromJson(responseBody, Response.class);
// Print out what you got
res.getData().stream().map(IdHolder::getId).forEach(System.out::println);
I am building an Android application which reads from themoviedb.org.
What I am trying to do is have the user enter a movie title and use that title to find its id.
When I run the query to search for movies, I get a response like:
{
"page": 1,
"results": [
{
"poster_path": "aaaaa.jpg",
"id": "11",
"description": "MovieDescription"
},
{
"poster_path": "bbbbb.jpg",
"id": "12",
"description": "MovieDescription2"
},
{
"poster_path": "ccccc.jpg",
"id": "13",
"description": "MovieDescription"
}
]
}
Using the Maven JSON library, I can fetch the results key as a string using json.get("results").
returning:
[
{
"poster_path": "aaaaa.jpg",
"id": "11",
"description": "MovieDescription"
},
{
"poster_path": "bbbbb.jpg",
"id": "12",
"description": "MovieDescription2"
},
{
"poster_path": "ccccc.jpg",
"id": "13",
"description": "MovieDescription"
}
]
But I want to convert the first of these results to another JSONObject so that I can get the movie's id from the first result.
I'm thinking that the way to do this is to convert the results value to a list of JSONObject and then use the json.get("id") method on the first object in the list. But I do not know how to do this conversion.
Any help would be appreciated.
You can use JSONObject.getJSONArray to get the result directly as a JSON Array:
JSONArray results = json.getJSONArray("results") // Get results as JSON Array
JSONObject first = results.getJSONObject(0) // Get first object as JSON Object
See: JSONObject#getJSONArray(String)
Given I have the following json structure:
{
"Role": {
"id": "5",
"name": "bb1",
"description": "desc1",
"PermissionDeck": [
{
"id": "7",
"Permission": [
{
"id": "398"
},
{
"id": "399"
},
{
"id": "400"
},
{
"id": "401"
},
{
"id": "402"
}
],
"Limit": [
{
"id": "4"
},
{
"id": "5"
}
]
}
]
}
}
If I want to cast this into a LinkedTreeMap result so that its content could be a retrieved by:
result.get("Role") returns Map
and
result.get("Role").get("PermissionDeck").size() == 5
and
result.get("Role").get("PermissionDeck").get(0).get("id") == 398
basically makes gson.fromjson recursively go into the structure, and fold any nested structure into LinkedTreeMap until it gets to the most inner layer, which then gets into LinkedTreeMap
Is this possible without writing custom recursive methods?
You can't. The closest you'll get is with JsonObject and using the appropriate getter for each nested member. In other words, your code needs to be explicit about what it expects in the JSON.
For example
JsonObject result = new Gson().fromJson(theJson), JsonObject.class);
System.out.println(result.getAsJsonObject("Role").getAsJsonArray("PermissionDeck").size());
will print 1 since you only have one element in the JSON array named PermissionDeck in the JSON object named Role in the root JSON object.
I have a json response.I want to get the value of lat and lng from the json response.But i didn't get the values.Please Help me.Below is my response.
{
"html_attributions": [],
"results": [
{
"geometry": {
"location": {
"lat": 9.493837,
"lng": 76.338506
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id": "2730a3d7ab068d666e61a02ce6160b4cd21a38c7",
"name": "Nagarjuna",
"place_id": "ChIJr0-U4vSECDsRtiALUlgZOzI",
"reference": "CmRcAAAA4yl72_x5llqvdshRJwuuntunXrYu33qdP5G7-I0CdHzcDsyd6wwqjxdNeqvT6vtRIoDoIk_WGNd62SYSoNEdBrpDrOcf5g5eZMj_vobhmF11mrujsQ_Yc7p-oGxQH0XtEhDNJdjQf_WlK_dRAckBzlA3GhQ_wzXs5RxoaxWDSEurm_R5syuovg",
"scope": "GOOGLE",
"types": [
"hospital",
"establishment"
],
"vicinity": "State Highway 40, Kodiveedu, Alappuzha"
},
{
"geometry": {
"location": {
"lat": 9.500542,
"lng": 76.341017
}
},
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id": "d5b6c81a53a346dea1263de7a777703bc72b8796",
"name": "SYDNEY OPTICALS",
"opening_hours": {
"open_now": true,
"weekday_text": []
},
"photos": [
{
"height": 422,
"html_attributions": [],
"photo_reference": "CnRnAAAA_jg-NlSrVKkDOP7wXhPhvFTD8NW4A4aDI_Ptl3F9c_qt9QwdztNTG9Cr51uGIphpEUMyhsTfhhaa-TlfoL8MUEffbguZJ1AhKUwzfe7Mbrvm2KW8Y1EQXVw_3FglxA4LM1hqWJCK_AV4xcvOw1vuHRIQ8_keBYr29H8jK145RQ_PkRoUgPZ0qzcSNdIntc2ZI4WvBIR-TBQ",
"width": 630
}
],
"place_id": "ChIJl9tvIV6ECDsR7Cmf3KkIl-4",
"reference": "CnRjAAAA3qhFUcb8P9akE8xw-KwfF6OU6qvy2cVX4Sg0qK_xCOfeUEyxoFgwof8rk-Z2BBJ7Z4m7ZTbfdp78wqFbeLfojQWPldq7XDfzX0pLScBSysebEp9P4XmrsAO5qyqSUveb5jWcJDkYiOLKgaKMzoWQphIQbldrdJ9iEDHkGiQ7tleNYxoUnjcjcynUDMftaErRUQbOn-GkWj0",
"scope": "GOOGLE",
"types": [
"store",
"hospital",
"health",
"establishment"
],
"vicinity": "Mullakkal, Alappuzha"
}
],
"status": "OK"
}
This is the google api response i used for getting the list of hospitals.Anybode plese help me.Thanks in advance.
Use these steps:
Create a model class for that Json Response
Use Gson to parse the response
Then create an object of the class
using the object get the data variable from the class
I hope I can help.
First, validate your JSON with http://jsonlint.com/
Second, use this site to generate POJO: http://www.jsonschema2pojo.org/
make sure that Annotation GSON and Source type JSON are clicked ON!
Copy your classes in to your project.
Third: use GSON in Android :) (Retrofit is good for this)
Supposing you use the json.org Implementation for Java:
String response = "{\"html_attributions\": [], \"results\": ...";
JSONObject jo = new JSONObject(response);
JSONObject result = jo.getJSONArray("results").getJSONObject(0);
JSONObject location = result.getJSONObject("geometry").getJSONObject("location");
double lat = location.getDouble("lat");
double lng = location.getDouble("lng");
try this
String response = "{\"html_attributions\": [], \"results\": ...";
JSONObject objResponce = new JSONObject(response);
JSONArray arrayResults=new JSONArray(objResponce.getString("results"));
if(arrayResults.length()>0)
{
for(int i=0;i<arrayResults.length();i++)
{
//--- get each json object from array -----
JSONObject objArrayResults = arrayResults.getJSONObject(i);
//--- get geometry json object from each object of array -----
JSONObject objGeometry=new JSONObject(objArrayResults.getString("geometry"));
//--- get location json object from geometry json object -----
JSONObject objLocation=new JSONObject(objGeometry.getString("location"));
System.out.println("Latitude :"+objLocation.getString("lat"));
System.out.println("Longitude :"+objLocation.getString("lng"));
}
}
I have a small test application I'm writing in Java to parse some JSON from the Reddit API. Some sample JSON I'm looking to parse would be like this:
[
{
"kind": "Listing",
"data": {
"modhash": "1jq62oyvwe15aaba7eb18b0b4363b567a00750766351e03dcc",
"children": [
{
"kind": "t3",
"data": {
"domain": "businessinsider.com",
"media_embed": {},
"levenshtein": null,
"subreddit": "Android",
"selftext_html": null,
"selftext": "",
"likes": null,
"saved": false,
"id": "n17u2",
"clicked": false,
"title": "CONFESSION OF A NON-APPLE-FANBOY: Even If The Samsung Galaxy Nexus Is Better, I'm Still Buying An iPhone",
"media": null,
"score": 0,
"over_18": false,
"hidden": false,
"thumbnail": "http://e.thumbs.redditmedia.com/sL0dCwGAvWqnY_sd.jpg",
"subreddit_id": "t5_2qlqh",
"author_flair_css_class": null,
"downs": 2,
"is_self": false,
"permalink": "/r/Android/comments/n17u2/confession_of_a_nonapplefanboy_even_if_the/",
"name": "t3_n17u2",
"created": 1323127132,
"url": "http://www.businessinsider.com/apple-iphone-versus-samsung-galaxy-nexus-2011-12",
"author_flair_text": null,
"author": "FormulaT",
"created_utc": 1323101932,
"num_comments": 0,
"ups": 1
}
}
],
"after": null,
"before": null
}
},
{
"kind": "Listing",
"data": {
"modhash": "1jq62oyvwe15aaba7eb18b0b4363b567a00750766351e03dcc",
"children": [],
"after": null,
"before": null
}
}
]
What I'm trying to accomplish is to get just a few values out of this JSON, e.g. the title and the author. I'm using Jackson to handle the JSON, and the code I'm using looks like this:
URLConnection conn = redditURL.openConnection();
BufferedReader buf = new BufferedReader(new InputStreamReader(conn.getInputStream()));
ObjectMapper mapper = new ObjectMapper();
RedditComment comment = mapper.readValue(buf, RedditComment.class);
Iterator itr = comment.getData().getChildren().listIterator();
I created the RedditComment and other needed classes using the JSONGen website (http://jsongen.byingtondesign.com/). However, when parsing the JSON from the BufferedReader, Jackson throws this exception:
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.test.RedditAPI.RedditComment out of START_ARRAY token
at [Source: java.io.BufferedReader#3ebfbbe3; line: 1, column: 1]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:212)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromArray(BeanDeserializer.java:869)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:597)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2723)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1877)
at com.test.RedditAPI.main.returnRedditComment(Main.java:17)
Does anyone have any ideas? I've been scratching my head for a few hours now.
EDIT: Thanks to #Chin Boon and #Chris, I came up with the following (after switching to GSON):
Gson gson = new Gson();
List<RedditComment> comment = gson.fromJson(buf, new TypeToken<List<RedditComment>>() {}.getType());
List<RedditChildren> children = comment.get(1).getData().getChildren();
System.out.println(children.get(1).getData().getAuthor());
but that throws the following exception:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.test.RedditAPI.RedditChildren
Apologies if I'm being a bother, I've looked around the API and there isn't any reference of LinkedHashMaps, so I don't know why it's popping up here.
The problem is that the response is an array of entries. Try:
List<RedditComment> comment = mapper.readValue(buf,new TypeReference<List<RedditComment>>(){});
if you have not already invested too much time into Jackson, may i recommend you looking at GSON, here is a tutorial that should have you started.
Google GSON API maps your JSON string into a domain object.
http://java.sg/parsing-a-json-string-into-an-object-with-gson-easily/
Also, you can use a JSON parser to see your JSON.