Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?(为什么 Gson fromJson 会抛出 JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?)
问题描述
(这篇文章旨在成为 规范问题,下面提供了示例答案.)
(This post is meant to be a canonical question with a sample answer provided below.)
我正在尝试使用 Gson#fromJson(String, Class)
.
I'm trying to deserialize some JSON content into a custom POJO type with Gson#fromJson(String, Class)
.
这段代码
import com.google.gson.Gson;
public class Sample {
public static void main(String[] args) {
String json = "{"nestedPojo":[{"name":null, "value":42}]}";
Gson gson = new Gson();
gson.fromJson(json, Pojo.class);
}
}
class Pojo {
NestedPojo nestedPojo;
}
class NestedPojo {
String name;
int value;
}
抛出跟随异常
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
at com.google.gson.Gson.fromJson(Gson.java:810)
at com.google.gson.Gson.fromJson(Gson.java:775)
at com.google.gson.Gson.fromJson(Gson.java:724)
at com.google.gson.Gson.fromJson(Gson.java:696)
at com.example.Sample.main(Sample.java:23)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
... 7 more
为什么 Gson 不能正确地将我的 JSON 文本转换为我的 POJO 类型?
Why can't Gson properly convert my JSON text to my POJO type?
推荐答案
如异常信息所述
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
在反序列化时,Gson 期待一个 JSON 对象,但找到了一个 JSON 数组.由于它不能从一个转换到另一个,它抛出了这个异常.
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.
此处描述了 JSON 格式.简而言之,它定义了以下类型:对象、数组、字符串、数字、null
,以及布尔值true
和false
.
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
.
在 Gson(和大多数 JSON 解析器)中,存在以下映射: JSON 字符串映射到 Java String
;JSON 数字映射到 Java Number
类型;JSON 数组映射到 Collection
类型或数组类型;JSON 对象映射到 Java Map
类型,或者通常是自定义 POJO 类型(不是前面提到过);null
映射到 Java 的 null
,布尔值映射到 Java 的 true
和 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 遍历您提供的 JSON 内容并尝试将其反序列化为您请求的相应类型.如果内容不匹配或无法转换为期望的类型,则会抛出相应的异常.
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.
在您的情况下,您提供了以下 JSON
In your case, you provided the following JSON
{
"nestedPojo": [
{
"name": null,
"value": 42
}
]
}
在根部,这是一个 JSON 对象,其中包含一个名为 nestedPojo
的成员,该成员是一个 JSON 数组.该 JSON 数组包含一个元素,即另一个具有两个成员的 JSON 对象.考虑到前面定义的映射,您希望这个 JSON 映射到一个 Java 对象,该对象具有一个名为 nestedPojo
的字段,该字段属于某个 Collection
或数组类型,其中该类型定义了两个分别命名为 name
和 value
的字段.
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.
但是,您已将 Pojo
类型定义为具有字段
However, you've defined your Pojo
type as having a field
NestedPojo nestedPojo;
既不是数组类型,也不是 Collection
类型.Gson 无法反序列化该字段对应的 JSON.
that is neither an array type, nor a Collection
type. Gson can't deserialize the corresponding JSON for this field.
相反,您有 3 个选项:
Instead, you have 3 options:
更改您的 JSON 以匹配预期类型
Change your JSON to match the expected type
{
"nestedPojo": {
"name": null,
"value": 42
}
}
更改您的 Pojo
类型以期望 Collection
或数组类型
Change your Pojo
type to expect a Collection
or array type
List<NestedPojo> nestedPojo; // consider changing the name and using @SerializedName
NestedPojo[] nestedPojo;
使用您自己的解析规则为 NestedPojo
编写和注册自定义反序列化器.例如
Write and register a custom deserializer for NestedPojo
with your own parsing rules. For example
class 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 fromJson 会抛出 JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么 Gson fromJson 会抛出 JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
基础教程推荐
- 如何强制对超级方法进行多态调用? 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01