如何让Jackson序列化包含属性尊重JAXB的required属性?
解决Jackson XML序列化中NON_NULL与JAXB @XmlElement(required=true)的冲突问题
这个场景确实挺常见的——全局配置了NON_NULL过滤空值,但又想让标记了JAXB @XmlElement(required=true)的字段即使为null也生成空标签,对吧?咱们来一步步解决这个矛盾:
问题根源
JsonInclude.Include.NON_NULL是全局生效的序列化策略,它会直接忽略所有值为null的字段,完全不会去检查该字段是否带有@XmlElement(required=true)注解,所以导致你需要的必填空标签无法生成。
解决方案:自定义字段包含逻辑
我们可以通过扩展Jackson的AnnotationIntrospector,来实现针对特定字段的包含规则覆盖:当字段带有@XmlElement(required=true)时,强制输出该字段(即使值为null),其他字段仍然遵循NON_NULL策略。
具体实现代码
import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector; import com.fasterxml.jackson.dataformat.xml.XmlAnnotationIntrospector; import jakarta.xml.bind.annotation.XmlElement; public class CustomXmlJaxbIntrospector extends AnnotationIntrospectorPair { public CustomXmlJaxbIntrospector() { super(new XmlAnnotationIntrospector(), new JaxbAnnotationIntrospector()); } @Override public Boolean hasInclude(AnnotatedMember member) { // 先检查字段是否标记了@XmlElement(required=true) XmlElement xmlElement = member.getAnnotation(XmlElement.class); if (xmlElement != null && xmlElement.required()) { // 强制返回true,让该字段即使为null也被序列化 return Boolean.TRUE; } // 其他字段遵循全局的NON_NULL规则 return super.hasInclude(member); } }
然后修改你的XmlMapper配置,替换成自定义的Introspector:
XmlMapper xmlMapper = new XmlMapper(); xmlMapper.setAnnotationIntrospector(new CustomXmlJaxbIntrospector()); xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
验证效果
假设你的POJO是这样的:
import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "test") public class TestPojo { @XmlElement(name = "some-value", required = true) protected String someValue; @XmlElement(name = "optional-value") protected String optionalValue; // getter/setter 省略 }
当你序列化一个someValue=null、optionalValue=null的对象时,会得到如下XML:
<test> <some-value/> </test>
可以看到:
- 标记了
required=true的some-value生成了空标签,符合JAXB的要求 - 未标记必填的
optional-value因为NON_NULL策略被忽略,完美匹配你的需求!
补充说明
如果同时需要支持Jackson自身的注解(比如@JsonProperty),只需调整自定义Introspector的构造方法,加入JacksonAnnotationIntrospector并调整优先级即可:
public CustomXmlJaxbIntrospector() { super(new AnnotationIntrospectorPair(new XmlAnnotationIntrospector(), new JacksonAnnotationIntrospector()), new JaxbAnnotationIntrospector()); }
内容的提问来源于stack exchange,提问作者Mateva
相关产品推荐
相关产品推荐

