我扩展了 rnd 的工作,因为它为所有字段启用了该功能,而不仅仅是其中一些。
这是一个您将添加到绑定中的模块,如下所示:
XmlMapper mapper = new XmlMapper();
XmlSerializerProvider provider = new XmlSerializerProvider(new XmlRootNameLookup());
provider.setNullValueSerializer(new NullSerializer());
mapper.setSerializerProvider(provider);
mapper.registerModule(new NullPointerModule());
NullPointerModule 实现了自己的自定义序列化程序来传递自省当前字段所需的属性。
NullPointerModule.java:
public class NullPointerModule extends SimpleModule implements java.io.Serializable {
private static final long serialVersionUID = 1L;
@Override
public void setupModule(SetupContext context) {
// Need to modify BeanDeserializer, BeanSerializer that are used
context.addBeanSerializerModifier(new XmlBeanSerializerModifier() {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (int i = 0, len = beanProperties.size(); i < len; ++i) {
BeanPropertyWriter bpw = beanProperties.get(i);
if (bpw.getClass().equals(BeanPropertyWriter.class)) {
beanProperties.set(i, new NullCheckedBeanPropertyWriter(bpw));
}
}
return beanProperties;
}
});
super.setupModule(context);
}
}
接下来是实际的 NullSerializer,它接受属性编写器并确定该字段是否需要 nil 字段。
NullSerializer.java:
public class NullSerializer extends JsonSerializer<Object> {
@SuppressWarnings("unused")
public void serializeWithProperty(BeanPropertyWriter propertyWriter, Object value, JsonGenerator jgen, SerializerProvider provider) {
ToXmlGenerator xGen = (ToXmlGenerator) jgen;
XmlElement annotation = null;
if (propertyWriter != null) {
AnnotatedMember member = propertyWriter.getMember();
annotation = member.getAnnotation(XmlElement.class);
}
try {
if (annotation != null) {
if (annotation.nillable()) {
xGen.writeStartObject();
XMLStreamWriter staxWriter = xGen.getStaxWriter();
staxWriter.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
staxWriter.writeAttribute("xsi:nil", "true");
xGen.writeEndObject();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
serializeWithProperty(null, value, jgen, provider);
}
}
最后是 propertyWriters 的覆盖。这有点小技巧,因为如果属性编写器本身被另一个模块中的另一个类替换,这可能会失败。
NullCheckedBeanPropertyWriter.java:
public class NullCheckedBeanPropertyWriter extends BeanPropertyWriter {
public NullCheckedBeanPropertyWriter(BeanPropertyWriter base) {
super(base);
}
@Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
final Object value = (_accessorMethod == null) ? _field.get(bean)
: _accessorMethod.invoke(bean);
// Null handling is bit different, check that first
if (value == null) {
if (_nullSerializer != null) {
gen.writeFieldName(_name);
if (_nullSerializer instanceof NullSerializer) {
NullSerializer nullSerializer = (NullSerializer) _nullSerializer;
nullSerializer.serializeWithProperty(this, bean, gen, prov);
return;
}
_nullSerializer.serialize(null, gen, prov);
}
return;
}
super.serializeAsField(bean, gen, prov);
}
}
然后可以使用 @XmlElement(nillable=true) 添加这些字段,以使它们满足您的需求。