You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何判断JSON属性为数组还是对象以解决解析类型不匹配错误

Expected begin array but it was begin object报错根源于实体类字段声明为数组/集合类型,但JSON实际返回单个对象,以下是具体解决方案:

兼容JSON单字段多类型(对象/数组)的Java解析方案

核心思路:无需提前硬编码检测类型,直接通过主流JSON解析库的内置配置或自定义反序列化逻辑即可自动适配,既满足需求又减少冗余代码。

1 基于Jackson实现(推荐,Java生态最常用)

Jackson内置了专门的配置项直接支持这种场景,无需额外编写逻辑。

1.1 定义实体类

统一把可能返回数组/对象的字段声明为集合类型:

// 家庭成员实体
public class FamilyMember {
    private String kinship;
    private String age;
    // 省略getter、setter、无参构造
}

// 根实体
public class User {
    private String name;
    private String age;
    private String phone;
    // 统一用List接收,返回单个对象时会自动封装为单元素列表
    private List<FamilyMember> family;
    // 省略getter、setter、无参构造
}

1.2 开启单值转数组配置

全局配置(适合所有接口都有这类兼容需求的场景)

普通Java项目代码配置:

ObjectMapper objectMapper = new ObjectMapper();
// 开启兼容:单个对象自动包装为对应类型的单元素集合
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

// 直接解析即可,两种格式都能正常转换
User user = objectMapper.readValue(jsonStr, User.class);

SpringBoot项目可以直接在配置文件中开启:

spring:
  jackson:
    deserialization:
      accept-single-value-as-array: true

单字段配置(仅给指定字段开启兼容)

如果不想全局开启该配置,可以给目标字段单独加自定义反序列化器。

2 基于Gson实现

Gson需要自定义TypeAdapter实现适配:

Type listType = new TypeToken<List<FamilyMember>>() {}.getType();
TypeAdapter<List<FamilyMember>> adapter = new TypeAdapter<List<FamilyMember>>() {
    @Override
    public void write(JsonWriter out, List<FamilyMember> value) throws IOException {
        // 序列化逻辑按需实现
    }

    @Override
    public List<FamilyMember> read(JsonReader in) throws IOException {
        List<FamilyMember> list = new ArrayList<>();
        // 判断当前节点类型
        if (in.peek() == JsonToken.BEGIN_OBJECT) {
            // 是对象,解析后加入列表
            FamilyMember member = new Gson().fromJson(in, FamilyMember.class);
            list.add(member);
        } else if (in.peek() == JsonToken.BEGIN_ARRAY) {
            // 是数组,正常解析
            in.beginArray();
            while (in.hasNext()) {
                FamilyMember member = new Gson().fromJson(in, FamilyMember.class);
                list.add(member);
            }
            in.endArray();
        }
        return list;
    }
};

// 注册适配器后解析即可
Gson gson = new GsonBuilder()
        .registerTypeAdapter(listType, adapter)
        .create();
User user = gson.fromJson(jsonStr, User.class);

3 手动检测类型的实现方案

如果确实需要先检测类型再做处理,可以先把JSON解析为树节点再判断:

// Jackson实现
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonStr);
JsonNode familyNode = rootNode.get("family");

if (familyNode.isArray()) {
    // 按数组逻辑处理
    List<FamilyMember> family = objectMapper.convertValue(familyNode, new TypeReference<List<FamilyMember>>() {});
} else if (familyNode.isObject()) {
    // 按对象逻辑处理
    FamilyMember family = objectMapper.convertValue(familyNode, FamilyMember.class);
}

内容的提问来源于stack exchange,提问作者Romeu Carvalho Antunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:48:02