Jackson反序列化时如何一次性获取所有不符合规范的错误字段名称
解决方案
方案一:基于Jackson原生能力实现(无额外依赖,适合仅需校验未知字段的场景)
你之前只拿到第一个错误字段,是因为DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES的默认逻辑是遇到第一个未知字段就终止反序列化、直接抛出异常,所以只会返回第一个错误信息。
你可以通过注册自定义的DeserializationProblemHandler来收集全量未知字段,具体实现如下:
- 自定义未知字段收集处理器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class UnknownFieldCollector extends DeserializationProblemHandler { // 线程安全的集合存储所有未知字段 private final List<String> unknownFields = Collections.synchronizedList(new ArrayList<>()); @Override public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException { unknownFields.add(propertyName); // 返回true表示跳过当前未知字段,继续反序列化流程 return true; } // 获取所有收集到的未知字段 public List<String> getUnknownFields() { return Collections.unmodifiableList(unknownFields); } }
- 反序列化时使用该处理器
// 每次反序列化创建独立的收集器,避免多线程数据混淆 UnknownFieldCollector collector = new UnknownFieldCollector(); ObjectMapper mapper = new ObjectMapper() // 注册自定义处理器 .addHandler(collector); // 执行反序列化,YourTargetClass替换为你实际的目标类 YourTargetClass targetObj = mapper.readValue(输入的JSON字符串, YourTargetClass.class); // 拿到所有错误字段 List<String> errorFields = collector.getUnknownFields(); if (!errorFields.isEmpty()) { // 可根据业务需求抛出包含所有错误字段的自定义异常 throw new IllegalArgumentException("存在非法字段:" + String.join("、", errorFields)); }
方案二:修复JSON Schema校验逻辑(适合需要复杂校验规则的场景)
你之前遇到的$: string found, object expected报错,核心问题是校验对象错误:你没有校验输入的原始JSON,反而校验了自己构建的空MyObject实例。修复后的代码如下:
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V201909); InputStream stream = TestClass.class.getResourceAsStream("/file.json"); JsonSchema schema = factory.getSchema(stream); // 注意:这里要把输入的原始JSON转成JsonNode,而不是转换自己构造的对象 JsonNode inputNode = mapper.readTree(输入的JSON字符串); Set<ValidationMessage> validationResult = schema.validate(inputNode);
调整后validationResult就会包含所有不符合Schema规范的错误信息,包括未知字段、类型不匹配等全量校验结果。
内容的提问来源于stack exchange,提问作者Disteonne
相关产品推荐
相关产品推荐

