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
相关产品推荐
相关产品推荐

