如何配置ObjectMapper仅在JSON包含类全部字段时完成对象转换?
嘿,这个需求Jackson本身就提供了好几种原生解决方案,比手动转JSONObject比对字段要简洁靠谱多了,给你梳理几个常用的方式:
方法1:给必填字段标注
@JsonProperty(required = true)(灵活可控) 这种方式适合你需要区分“必填字段”和“可选字段”的场景,只给必须存在的字段加上注解,然后配置ObjectMapper开启校验:
首先给你的ABC类字段加上注解:
public class ABC { @JsonProperty(required = true) private String mem1; @JsonProperty(required = true) private String mem2; @JsonProperty(required = true) private String mem3; // 记得添构造器、getter/setter方法 }
然后配置ObjectMapper,让它严格检查required=true的字段是否存在:
ObjectMapper mapper = new ObjectMapper(); // 开启缺失构造器属性时抛出异常(配合@JsonProperty(required=true)生效) mapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, true); // 确保不会忽略标注了required的字段校验 mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, true);
这样当JSON字符串缺少任何一个标注了required=true的字段时,Jackson会直接抛出JsonMappingException,转换失败,完全符合你的要求。
方法2:全局开启强制检查所有字段(适用于全字段必填的场景)
如果你的ABC类所有字段都是必须存在的,没有可选字段,那可以直接用全局配置,不用给每个字段加注解:
ObjectMapper mapper = new ObjectMapper(); // 开启全局校验:只要目标类的字段无默认值且JSON中缺失,就抛出异常 mapper.configure(DeserializationFeature.FAIL_ON_MISSING_PROPERTIES, true);
⚠️ 注意:如果字段有默认值(比如private String mem2 = "default";),Jackson会自动用默认值填充,不会触发异常。所以这个配置最适合所有字段都没有默认值的场景。
方法3:自定义反序列化器(复杂场景自定义)
如果上面两种方法满足不了你的特殊需求(比如要自定义错误提示、或者有复杂的字段校验逻辑),可以写一个自定义反序列化器:
public class ABCDeserializer extends StdDeserializer<ABC> { public ABCDeserializer() { super(ABC.class); } @Override public ABC deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); // 手动检查所有必填字段是否存在 String[] requiredFields = {"mem1", "mem2", "mem3"}; for (String field : requiredFields) { if (!node.has(field)) { throw new JsonMappingException(p, String.format("JSON必须包含字段:%s", field)); } } // 手动将JSON节点转换为ABC对象 ABC abc = new ABC(); abc.setMem1(node.get("mem1").asText()); abc.setMem2(node.get("mem2").asText()); abc.setMem3(node.get("mem3").asText()); return abc; } }
然后把这个反序列化器注册到ObjectMapper中:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(ABC.class, new ABCDeserializer()); mapper.registerModule(module);
这种方式完全由你掌控校验逻辑,还能返回更精准的错误信息。
内容的提问来源于stack exchange,提问作者Akshay Srivastava
相关产品推荐
相关产品推荐

