当前位置: 首页 > 知识库问答 >
问题:

为什么Gson fromJson抛出JsonSyntaxException:应该是BEGIN_对象,但却是BEGIN_数组?

支劲
2023-03-14

(这篇文章是一个典型的问题,下面提供了一个示例答案。)

我正试图用Gson#fromJson(String,Class)将一些JSON内容反序列化为自定义POJO类型。

这段代码

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类型?

共有2个答案

陈松
2023-03-14
class Pojo {
  NestedPojo nestedPojo;
}

在json中有一个nestedPojo数组,因此要么更改代码

  NestedPojo[] nestedPojo;

或者更改json字符串

String json = "{\"nestedPojo\":{\"name\":null, \"value\":42}}";
乐正浩博
2023-03-14

正如异常消息所述

Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo

在反序列化时,Gson需要一个JSON对象,但找到了一个JSON数组。因为它无法从一个转换到另一个,所以抛出了这个异常。

这里描述了JSON格式。简而言之,它定义了以下类型:对象、数组、字符串、数字、null,以及布尔值truefalse

在Gson(以及大多数JSON解析器)中,存在以下映射:一个JSON字符串映射到一个Java字符串;JSON编号映射到Java编号类型;JSON数组映射到集合类型或数组类型;JSON对象映射到JavaMap类型,或者通常映射到自定义POJO类型(前面没有提到)null映射到Java的null,布尔值映射到Java的truefalse

Gson遍历您提供的JSON内容,并尝试将其反序列化为您请求的相应类型。如果内容不匹配或无法转换为预期类型,它将抛出相应的异常。

在您的案例中,您提供了以下JSON

{
    "nestedPojo": [
        {
            "name": null,
            "value": 42
        }
    ]
}

从根本上说,这是一个JSON对象,它包含一个名为nestedPojo的成员,这是一个JSON数组。该JSON数组包含一个元素,另一个JSON对象有两个成员。考虑到前面定义的映射,您可能希望这个JSON映射到一个Java对象,该对象具有一个名为nestedPojo的字段,该字段的名称是集合或数组类型,其中该类型分别定义了两个字段,分别名为namevalue

但是,您已经将Pojo类型定义为具有字段

NestedPojo nestedPojo;

这既不是数组类型,也不是集合类型。Gson无法反序列化此字段对应的JSON。

相反,你有3个选择:

>

{
    "nestedPojo": {
        "name": null,
        "value": 42
    }
}

将您的Pojo类型更改为集合或数组类型

List<NestedPojo> nestedPojo; // consider changing the name and using @SerializedName
NestedPojo[] nestedPojo;

使用您自己的解析规则为NestedPojo编写并注册一个自定义反序列化器

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();
 类似资料:
  • 当我只收到列表中的一个项目时,就会出现这个错误。我在服务器端REST Web服务中使用Jersey,只有当列表返回一个元素时,以及当它有但当它有多个异常时,它工作得非常完美,我就是这样做的: Jersey为什么不发送包含一个项目的列表?是泽西岛的虫子吗?有没有办法让它始终序列化为数组? 这是web服务返回0元素时的JSON数据: 这是web服务返回1个元素时的JSON数据: 当web服务返回超过1

  • 这个错误又回来了! 我是改装的初学者,我看过这篇文章:改装:预期BEGIN_OBJECT但BEGIN_ARRAY 但是即使我试着让它适应我的模型,我仍然不能让它工作。所以我的错误是: 我得到的是: 解析类的属性: IoTGenericDevice子类的属性: 改装电话: 经理:

  • 使用改装库来使用一项服务,我为我的界面、模型以及如何使用界面添加了代码。 我不断收到一个GSON抛出的“预期的BEGIN_对象,但是BEGIN_数组” 界面 模范公立班学生{ 我怎么称呼方法

  • 嗨,我是改装2.0库的新手,我在解析一些json时遇到了问题。我在Stackoverflow上看了一些其他的解决方案,但我的问题运气不佳。我试图用改装2.0从Android系统调用一个api。但它抛出了预期的错误BEGIN_ARRAY但BEGIN_OBJECT。 我对web api的回应是: 这就是我的模型类: 这是我的界面: 这就是我打电话的方式:

  • 我知道以前有人问过很多这个问题,但在我的情况下,我找不到解决办法。我请求获得关于POJO(电影)列表的json回复 虽然这是我第一次使用改型,但我在标题中遇到了问题。我正在创建的url是正确的,下面是响应的示例: 这是我的模特 } 我的@GET 我的数据请求类 最后,我想在我的主要活动中做些什么

  • 您好,我是新来的改装库,我有问题解析一些json。我已经研究了Stackoverflow的一些其他解决方案,但我的问题没有太多的运气。我正在尝试一个简单的网络服务。如有任何建议,将不胜感激。。 json文件 请求方法 Employees.java 雇员萨皮。JAVA 我得到的错误是 我理解错误是说数据是一个对象,它应该以数组开头,但我无法计算出来。。谢谢