Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
As the exception message states
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
while deserializing, Gson was expecting a JSON object, but found a JSON array. Since it couldn't convert from one to the other, it threw this exception.
The JSON format is described here. In short, it defines the following types: objects, arrays, strings, numbers, null
, and the boolean values true
and false
.
In Gson (and most JSON parsers), the following mappings exist: a JSON string maps to a Java String
; a JSON number maps to a Java Number
type; a JSON array maps to a Collection
type or an array type; a JSON object maps to a Java Map
type or, typically, a custom POJO type (not mentioned previously); null
maps to Java's null
, and the boolean values map to Java's true
and false
.
Gson iterates through the JSON content that you provide and tries to deserialize it to the corresponding type you've requested. If the content doesn't match or can't be converted to the expected type, it'll throw a corresponding exception.
In your case, you provided the following JSON
{
"nestedPojo": [
{
"name": null,
"value": 42
}
]
}
At the root, this is a JSON object which contains a member named nestedPojo
which is a JSON array. That JSON array contains a single element, another JSON object with two members. Considering the mappings defined earlier, you'd expect this JSON to map to a Java object which has a field named nestedPojo
of some Collection
or array type, where that types defines two fields named name
and value
, respectively.
However, you've defined your Pojo
type as having a field
NestedPojo nestedPojo;
that is neither an array type, nor a Collection
type. Gson can't deserialize the corresponding JSON for this field.
Instead, you have 3 options:
Change your JSON to match the expected type
{
"nestedPojo": {
"name": null,
"value": 42
}
}Change your
Pojo
type to expect aCollection
or array typeList<NestedPojo> nestedPojo; // consider changing the name and using @SerializedName
NestedPojo[] nestedPojo;Write and register a custom deserializer for
NestedPojo
with your own parsing rules. For exampleclass Custom implements JsonDeserializer<NestedPojo> {
@Override
public NestedPojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
NestedPojo nestedPojo = new NestedPojo();
JsonArray jsonArray = json.getAsJsonArray();
if (jsonArray.size() != 1) {
throw new IllegalStateException("unexpected json");
}
JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); // get only element
JsonElement jsonElement = jsonObject.get("name");
if (!jsonElement.isJsonNull()) {
nestedPojo.name = jsonElement.getAsString();
}
nestedPojo.value = jsonObject.get("value").getAsInt();
return nestedPojo;
}
}
Gson gson = new GsonBuilder().registerTypeAdapter(NestedPojo.class, new Custom()).create();
GSON throwing Expected BEGIN_OBJECT but was BEGIN_ARRAY?
The problem is you're telling Gson
you have an object of your type. You don't. You have an array of objects of your type. You can't just try and cast the result like that and expect it to magically work ;)
The User guide for Gson
Explains how to deal with this:
https://github.com/google/gson/blob/master/UserGuide.md
This will work:
ChannelSearchEnum[] enums = gson.fromJson(yourJson, ChannelSearchEnum[].class);
But this is better:
Type collectionType = new TypeToken<Collection<ChannelSearchEnum>>(){}.getType();
Collection<ChannelSearchEnum> enums = gson.fromJson(yourJson, collectionType);
Gson issue:- Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1
Use the second case, but replace
private SubTasks subTasks ;
with
private List<SubTasks> subTasks ;
The clue was in the error.
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 276 path $.subTasks
Given your java classes, it was expecting an object named subTasks but found an array.
So change it to an array and you are gold.
The first case is probably correct, if you end up parsing an array of SMTStatus
gson.fromJson Expected BEGIN_OBJECT but was BEGIN_ARRAY because of how the object is stored
I just added [ ] before and after my JSON object in the exec sql statement + took the advice of the comment above and it works..for now
the code became thus:
db.execSQL("insert into favorites (obj) values ('["+g.toJson(items.get(getAdapterPosition()),Hotel.class).toString()+"]') ;");
//and when retrieved:
Gson gson = new Gson();
Type hotelListType = new TypeToken<ArrayList<Hotel>>(){}.getType();
ArrayList<Hotel> h = gson.fromJson(json, hotelListType );
this works
gson.fromJson Expected BEGIN_OBJECT but was BEGIN_ARRAY
Looks like the JSON string (rankJSON
) is an array of JSON documents not a single JSON document.
If you log that JSON you'll see that it starts with [
e.g.
[
{
...
}
]
You are attempting to deserialize it into a single RankAPI
, you should instead deserialize it into a List<RankAPI>
, for example;
List<RankAPI> r = gson.fromJson(rankJSON, new TypeToken<ArrayList<RankAPI>>(){}.getType());
Here's a test case to verify this behaviour:
@Test
public void twoWayTransform() {
Gson gson = new GsonBuilder().serializeNulls().create();
List<RankAPI> incomings = Arrays.asList(new RankAPI(), new RankAPI());
String json = gson.toJson(incomings);
// use TypeToken to inform Gson about the type of the elements in the generic list
List<RankAPI> fromJson = gson.fromJson(json, new TypeToken<ArrayList<RankAPI>>(){}.getType());
assertEquals(2, fromJson.size());
for (RankAPI incoming : incomings) {
// this will pass if RankAPI has an equals() method
assertTrue(fromJson.contains(incoming));
}
}
OkHttp / Retrofit / Gson: Expected BEGIN_OBJECT but was BEGIN_ARRAY
Error: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
As the error clearly says, you are trying to parse JSONArray into a JSONObject
@GET("characters/house/{house}")
Call<Data> getPersonajes(@Path("house") String house);
This service method expecting JSONObject, but according the logcat shared by in the image, the response is giving JSONArray. Instead you should parse it as:
@GET("characters/house/{house}")
Call<List<Personaje>> getPersonajes(@Path("house") String house)
GSON throwing “Expected BEGIN_OBJECT but was BEGIN_ARRAY”
Your input is not valid Json. It should look like this:
{
"1": {
"Butter": [
{
"x": 16.23,
"y": 21.11
},
{
"x": 18.18,
"y": 26.67
}
]
},
"2": {
"Butter": [
{
"x": 41.98,
"y": 47.62
}
]
}
}
JsonSyntaxException Expected BEGIN_OBJECT but was BEGIN_ARRAY at path
Instead of jsonObject.get("rows")
, use the below syndax
jsonObject.getAsJsonArray("rows")
Java gson error: Expected BEGIN_OBJECT but was BEGIN_ARRAY (but my type map is correct?)
That's because GroupedTotals
isn't a list, it is an object that contains a list.
Valid json that would convert into an instance of that class would look like
{
"BSRecvDestDNSName": [
...
]
}
Alternately, you could obtain the Type
for a list and convert directly to it. For instance, using your original json, this code:
Type type = new TypeToken<List<Map<String, Float>>>() {}.getType();
List<Map<String, Float>> myList = gson.fromJson(output, type);
System.out.println("myList='"+myList+"'");
Outputs
myList='[{aws.amazon.com=426788.0}, {atsv2-fp.wg1.b.yahoo.com=141154.0}, {e2svi.x.incapdns.net=140445.0}, {stackoverflow.com=87624.0}, {a-sg03sl05.insnw.net=56665.0}]'
Related Topics
How to Create Interface Between Fragment and Adapter
How to Create Android Facebook Key Hash
Loading Resources Like Images While Running Project Distributed as Jar Archive
Change Date Format in a Java String
Avoiding Nullpointerexception in Java
Run a Java Application as a Service on Linux
How to Set Java_Home in Linux For All Users
Downloading Java Jdk on Linux Via Wget Is Shown License Page Instead
Java Processbuilder: Resultant Process Hangs
Will System.Currenttimemillis Always Return a Value ≫= Previous Calls
Do Line Endings Differ Between Windows and Linux
Relation Between Memory Host and Memory Arguments Xms and Xmx from Java
Java Generics Type Erasure: When and What Happens
How to Read Input from the Console Using the Scanner Class in Java
Virtual Memory Usage from Java Under Linux, Too Much Memory Used
Error Java.Lang.Outofmemoryerror: Gc Overhead Limit Exceeded