gpt4 book ai didi

java - 为什么 Gson fromJson 抛出 JsonSyntaxException : Expected BEGIN_OBJECT but was BEGIN_ARRAY?

转载 作者:搜寻专家 更新时间:2023-10-30 21:14:44 25 4
gpt4 key购买 nike

(这篇文章是 canonical question,下面提供了示例答案。)


我正在尝试使用 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 类型?

最佳答案

如异常消息所述

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

反序列化时,Gson 期待一个 JSON 对象,但找到了一个 JSON 数组。由于它无法从一个转换为另一个,因此抛出此异常。

JSON格式描述here .简而言之,它定义了以下类型:对象、数组、字符串、数字、null。 , 和 boolean 值 truefalse .

在 Gson(和大多数 JSON 解析器)中,存在以下映射:JSON 字符串映射到 Java String ; JSON 数字映射到 Java Number类型; JSON 数组映射到 Collection类型或数组类型; JSON 对象映射到 Java Map输入或通常是自定义 POJO类型(之前未提及); null映射到 Java 的 null , boolean 值映射到 Java 的 truefalse .

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

在您的情况下,您提供了以下 JSON

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

在根目录下,这是一个 JSON 对象,其中包含一个名为 nestedPojo 的成员这是一个 JSON 数组。该 JSON 数组包含一个元素,另一个具有两个成员的 JSON 对象。考虑到前面定义的映射,您希望此 JSON 映射到一个 Java 对象,该对象具有一个名为 nestedPojo 的字段。一些Collection或数组类型,其中该类型定义了两个名为 name 的字段和 value , 分别。

但是,您已经定义了 Pojo键入具有字段

NestedPojo nestedPojo;

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

相反,您有 3 个选择:

  • 更改您的 JSON 以匹配预期的类型

    {
    "nestedPojo": {
    "name": null,
    "value": 42
    }
    }
  • 更改您的 Pojo键入以期待 Collection或数组类型

    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();

关于java - 为什么 Gson fromJson 抛出 JsonSyntaxException : Expected BEGIN_OBJECT but was BEGIN_ARRAY?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33621808/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com