GSON exception: Expected BEGIN_ARRAY but was BEGIN_OBJECT - java

I'm getting a JSON response (list of items) from a .NET WS, so that I want to transform to a List in my Android app. But when using GSON library, I get the following exception:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
JSON response:
{
"d": [
{
"Id":1,
"Name":"Name1",
"Email":"name1#gmail.com"
},
{
"Id":2,
"Name":"Name2",
"Email":"name2#gmail.com"
}
]
}
Android GSON code:
Gson gson = new Gson();
Type listType = new TypeToken<List<User>>(){}.getType();
List<User> users = (List<User>) gson.fromJson(response, listType);
As far as I understand, JSON is returning a list of items, and I'm also trying to parse to a list of items, so I don't understand the problem.
Thanks in advance

Your JSON is { ... }, so not a list, but d is a list.
This is completely untested, but you should do something like this:
class Foo {
List<User> d;
}
Gson gson = new Gson();
Foo foo = gson.fromJson(response, Foo.class);
List<User> users = foo.d;

Related

How do I Convert JSON Array into ArrayList<ClassType> in Java?

This is my input JSON From which I have to fetch interLockingGrids and store it into ArrayList<ClassType>. I have searched enough already but didn't find exactly what I want. Is there is any simplest way?
{"entity":"MasterGrid",
"data" :"{\"name\":\"MA_Pune\",
\"coordinates\" : [
{\"lat\":18.553449789265677,\"lng\":73.77419574114515},{\"lat\":18.554232972087224,\"lng\":73.77367002817823},{\"lat\":18.556135000463573,\"lng\":73.77144913093571},{\"lat\":18.555148376025496,\"lng\":73.7700973257704},{\"lat\":18.55309341985624,\"lng\":73.77075145899971},{\"lat\":18.5530421437421,\"lng\":73.77312207276918} ] ,
\"interLockingGrids\": [
{\"name\":\"Test1\",\"type\":\"CLUSTER\",\"coordinates\":[{\"lat\":18.555151666563823,\"lng\":73.7700902617189},{\"lat\":18.556135000463573,\"lng\":73.77144913093571},{\"lat\":18.556135000463573,\"lng\":73.77144913093571},{\"lat\":18.556135000463573,\"lng\":73.77144913093571},{\"lat\":18.556135000463573,\"lng\":73.77144913093571},{\"lat\":18.556135000463573,\"lng\":73.77144913093571}],\"isActive\":true,\"colorCode\":\"#D0983C\"} ,
{\"name\":\"Test2\",\"type\":\"CLUSTER\",\"coordinates\":[{\"lat\":18.5530421437421,\"lng\":73.77312207276918},{\"lat\":18.553449789265677,\"lng\":73.77419574114515},{\"lat\":18.55238201763598,\"lng\":73.7743998478852}],\"isActive\":true,\"colorCode\":\"#8E75B7\"} ] ,
"operation":"GRID_OPERATION",
"description":"Baner_Test",
"submittedBy":"m#abc.com",
"submittedById":4,
"submittedByType":"OPS" }
In a recent project I did something similar:
public List<MyType> parseJsonToListOfMyType(String json) {
Gson gson = new Gson();
JsonArray job = gson.fromJson(json, JsonArray.class);
Type listType = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(job, listType);
}

Using Gson to parse JSON with Objects but needing to exclude Arrays

I have a need to parse a JSON string containing Objects, but there can also be Arrays in the JSON, which I don't need, and it's currently crashing with:
com.google.gson.JsonSyntaxException:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
If I remove all the Arrays from the JSON, it works perfectly fine to parse the JSON with my POJO using the following code:
Type type = new TypeToken<Map<String, UsersPOJO>>(){}.getType();
Map<String, UsersPOJO> myUsers = gson.fromJson(JSONString, type);
But I'm having no luck parsing whenever there's Arrays in the JSON. I don't need, nor do I want to parse the Arrays, but if it's necessary, parsing the Arrays and then discarding the result would be okay.
How do I accomplish this with Gson? Or any other Java JSON library for that matter. Gson isn't a requirment.
This is an example of the JSON I'd be parsing:
{
"1002001":{
"level":2,
"name":"CaptKrunch",
"uid":1002001,
"user":{
"age":21,
"city":"None",
"country":"United States",
"creation":1269969663
},
"meta":{
"score":1762,
"rank":78
}
},
"1003001":{
"level":11,
"name":"LtRaine",
"uid":1003001,
"user":{
"age":35,
"city":"LA",
"country":"United States",
"creation":1269369663
},
"meta":{
"score":11562,
"rank":11
}
},
"tags_1002001": [
"conqurer",
"almighty"
]
}
You can skip array, if parse JSON string to JsonElement and iterate all elements:
Gson gson = new Gson();
//Type type = new TypeToken<Map<String, UsersPOJO>>(){}.getType();
//Map<String, UsersPOJO> myUsers = gson.fromJson(jsonString, type);
JsonParser parser = new JsonParser();
JsonElement topElement = parser.parse(jsonString);
Map<String, UsersPOJO> myUsers = new HashMap<>();
for (Map.Entry<String, JsonElement> entry : topElement.getAsJsonObject().entrySet()) {
if (entry.getValue().isJsonArray()) {
//skip or process array
} else {
myUsers.put(entry.getKey(), gson.fromJson(entry.getValue(), UsersPOJO.class));
}
}

Getting the values from a JSON string in Java using GSON

I hope someone can show me where i'm doing it wrong...
I'm using sendgrid for my email tracking and it is posting a JSON like the following:
[
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337966815,
"event": "click",
"url": "http://sendgrid.com"
"userid": "1123",
"template": "welcome"
}
]
Now i want to get the value of for example for "timestamp" which is 1337966815 . I've tried the following:
StringBuffer jb = new StringBuffer();
String line = null;
try {
BufferedReader reader = req.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
} catch (Exception e) { /*report an error*/ }
String jsonString = jb.toString();
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonString, JsonObject.class);
String timeStam = jsonObject.get(timestamp).toString();
The string of jsonString gives me the following which i think is in the right format:
[ { "email": "john.doe#sendgrid.com", "timestamp": 1337966815, "event": "click", "url": "http://sendgrid.com" "userid": "1123", "template": "welcome" }]
But i'm getting the following error at this line of code - JsonObject jsonObject = gson.fromJson(jsonString, JsonObject.class);
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 52
What am I doing wrong? Is it the format of jsonString that is confusing the JsonObject?
Any help would be very much appreciated.
Kind regards
Francois
The JSON you show in both examples is invalid. There is a comma missing after "url":"http://sendgrid.com"
Ignoring that, the JSON you show is an array of JSON objects, not an object. This is what the [] denotes (correcting the missing comma):
[
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337966815,
"event": "click",
"url": "http://sendgrid.com",
"userid": "1123",
"template": "welcome"
}
]
If you are not mapping this JSON to a Java POJO, then you would want to use Gson's JsonParser to parse your String to a JsonElement (Note you could even use it to parse directly from the Stream, but this if for how you have your code now).
JsonElement je = new JsonParser().parse(jsonString);
Now you have what's called a "parse tree". This JsonElement is the root. To access it as an array you're going to do:
JsonArray myArray = je.getAsJsonArray();
You only show this array containing one object, but let's say it could have more than one. By iterating through the array you can do:
for (JsonElement e : myArray)
{
// Access the element as a JsonObject
JsonObject jo = e.getAsJsonObject();
// Get the `timestamp` element from the object
// since it's a number, we get it as a JsonPrimitive
JsonPrimitive tsPrimitive = jo.getAsJsonPrimitive("timestamp");
// get the primitive as a Java long
long timestamp = tsPrimitive.getAsLong();
System.out.println("Timestamp: " + timestamp);
}
Realize that Gson primarily is meant for Object Relational Mapping where you want to take that JSON and have it converted to a Java object. This is actually a lot simpler:
public class ResponseObject {
public String email;
public long timestamp;
public String event;
public String url;
public String userid;
public String template;
}
Because you have array of these, you want to use a TypeToken and Type to indicate your JSON is a List of these ResponseObject objects:
Type myListType = new TypeToken<List<ResponseObject>>(){}.getType();
List<ResponseObject> myList = new Gson().fromJson(jsonString, myListType);

parse Json to Map<String,String>

I have Json response like :
[
{
"first_name": "fname1",
"last_name": "lname1"
},
{
"first_name": "fname2",
"last_name": "lname2",
"city_name": "paris"
},
{
"first_name": "fname2",
"last_name": "lname2",
"city_name": "paris",
"Address": "1st Ave"
}
.
.
.
]
and my fields in JsonObject is dynamic so i can't use a class with predefined fields , so i've decided to use Map to parse the Json response as below :
Collection<List<Map<String,String>>> list_Objects = null;
Reader reader = new InputStreamReader(is);
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<List<Map<String,String>>>>(){}.getType();
list_objects = gson.fromJson(reader, collectionType);
but it throws me this error :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1
im not expert in Json parsing so please tell me where is my mistake or if there is another way to implement such behavior i would be very appreciated.
I think the problem is with your Collection wrapper on the List one.
You just need to define the list_Objects as List<Map<String, String>>.
I just tried the following with Jackson's ObjectMapper (which should work the same as GSON) and it worked ok:
List<Map<String, String>> list_objects = objectMapper.readValue(jsonString, new TypeReference<List<Map<String, String>>>(){});
The result is a List of LinkedHashMap objects.
For your GSON example, you just need to remove the Collection<>, or the List<> if you prefer.
If I'm reading this correctly, you're defining your list twice.
Collection<List<Map<String, String>>> would map to a structure like
[ [ {"bla": "bla"}, {"bla": "bla"} ], [ {"foo": "bar"}, ... ], ... ]
(because List is a kind of Collection). So, try using List<Map<String, String>> and see if that works...

Parsing json webservice Response with Gson (Expected BEGIN_OBJECT but was BEGIN_ARRAY)

I'm trying to parse the spotify web-service response to get an artists' tracks which is like this:
{
"info": {
"num_results": 2974,
"limit": 100,
"offset": 0,
"query": "foo",
"type": "track",
"page": 1
},
"tracks": [
{
"album": {
"released": "2009",
"href": "spotify:album:1zCNrbPpz5OLSr6mSpPdKm",
"name": "Greatest Hits",
"availability": {
"territories": "AD AR AT AU BE BG BO BR CA CH CL CO CR CY CZ DE DK DO EC EE ES FI FR GB GR GT HK HN HU IE IS IT LI LT LU LV MC MT MX MY NI NL NO NZ PA PE PH PL PT PY RO SE SG SI SK SV TR TW US UY"
}
},
"name": "Everlong",
"popularity": "0.79",
"external-ids": [
{
"type": "isrc",
"id": "USRW29600011"
}
],
"length": 249.986,
"href": "spotify:track:07q6QTQXyPRCf7GbLakRPr",
"artists": [
{
"href": "spotify:artist:7jy3rLJdDQY21OgRLCZ9sD",
"name": "Foo Fighters"
}
],
"track-number": "3"
}]
}
I am using the Gson library to do this. So far I have tried this in my java code:
JsonParser parser = new JsonParser();
JsonObject jObject = parser.parse(jsonString).getAsJsonObject();
JsonArray jArray = jObject.get("tracks") .getAsJsonArray();
Gson gson = new Gson();
List<Track> trackArr = new ArrayList<Track>();
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackColl = gson.fromJson(jArray.toString(), collectiontype);
But I am getting the error : com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
I don't understand why is it expecting begin object if I am doing "getAsJsonArray()" when trying to get the "tracks" object whihc in the json string is an array [].
The list of 'Track' was when I was doing this in a loop to get all the tracks into an array:
for (JsonElement jsonElement : jArray) {
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackCol = gson.fromJson(jsonElement, collectiontype);
trackArr.add((Track) trackCol);
}
What am I doind wrong here ?
I appreciate any guidance.
You don`t have to use extra library to parse a JSON file. Also use this link to read your JSON file in a human readable way.
Use the Native one as the following example:
Imports:
import org.json.JSONArray;
import org.json.JSONObject;
The code of parsing will be:
JSONObject fileJSONObject = new JSONObject(response);
JSONObject infoJSONObject = fileJSONObject.getJSONObject("info");
JSONArray tracksJSONArray = fileJSONObject.getJSONArray("tracks");
//Parsing the info
String trackType = infoJSONObject.getString("type");
String trackLimit = infoJSONObject.getString("limit");
//The rest of attributes
//Parsing the track list
JSONObject object;
for(int i=0;i<tracksJSONArray.length();i++){
object = tracksJSONArray.getJSONObject(i);
String trackName = object.getString("name");
//The rest of attributes
}
I recommend for you to Create a track class that contain all the needed attributes and their setter and getter and at the end of the parsing of each track create a new track.
I hope it helps
You can use my lib for solve this problem. For example you can do it.
private static List<Object> SpotifyTest()
{
InformationHandler informationHandler = null;
Injector injector = Guice.createInjector(new Module());
informationHandler = injector.getInstance(SpotifyService.class);
informationHandler.executeWithValue("la bamba");
return informationHandler.getDataModel();
}
The solution returns a List with a lot of HashMap where each key is a enumeration of key on service, the enumarator is:
public enum SpotifyKey
{
ALBUM_RELEASED,
ALBUM_HREF,
ALBUM_NAME,
ALBUM_AVAILABILITY,
NAME,
POPULARITY,
LENGTH,
HREF,
ARTIST_HREF,
ARTIST_NAME,
TRACK_NUMBER,
ID
}
Also you can view the code on github https://github.com/WeCodeMx/WCMPopularService/tree/develop

Categories