Jackson自定义注释用于自定义NULL值序列化

Igo*_*bak 5 java jackson

根据这个答案:https: //stackoverflow.com/a/43342675/5810648

我写了这样的序列化器:

public class CustomSerializer extends StdSerializer<Double> implements ContextualSerializer {

    private final NAifNull annotation;

    public CustomSerializer() {
        super(Double.class);
        this.annotation = null;
    }

    public CustomSerializer(NAifNull annotation) {
        super(Double.class);
        this.annotation = annotation;
    }

    @Override
    public void serialize(Double value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (annotation != null && value == null) {
            gen.writeString("N/A");
        } else {
            gen.writeNumber(value);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
        NAifNull annotation = property.getAnnotation(NAifNull.class);
        return new CustomSerializer(annotation);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果注释存在且字段为,则Witch应该写字符串"N/A" null.但是serialize只为非空字段调用方法.

另外,我试着打电话setNullValueSerializer:

@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
    NAifNull annotation = property.getAnnotation(NAifNull.class);
    prov.setNullValueSerializer(new CustomNullSerializer(annotation));
    return new CustomSerializer(annotation);
}
Run Code Online (Sandbox Code Playgroud)

有了这样的实现:

private static class CustomNullSerializer extends JsonSerializer<Object> {
    private final NAifNull annotation;

    public CustomNullSerializer(NAifNull annotation) {
        this.annotation = annotation;
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (annotation != null) {
            gen.writeString("N/A");
        } else {
            gen.writeNull();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但没有结果.

如何以这种方式处理空字段?

更新

根据讨论:https: //github.com/FasterXML/jackson-databind/issues/2057

prov.setNullValueSerializer(new CustomNullSerializer(annotation));
Run Code Online (Sandbox Code Playgroud)

不应该从CreateContextual方法调用.

cas*_*lin 6

使用a BeanSerializerModifier特定属性自定义null序列化程序:

public class CustomBeanSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, 
           BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        for (BeanPropertyWriter beanProperty : beanProperties) {
            if (beanProperty.getAnnotation(NAifNull.class) != null) {
                beanProperty.assignNullSerializer(new CustomNullSerializer());
            }
        }

        return beanProperties;
    }
}
Run Code Online (Sandbox Code Playgroud)

其中@NAifNullCustomNullSerializer定义如下:

public class CustomNullSerializer extends JsonSerializer<Object> {

    @Override
    public void serialize(Object value, JsonGenerator jgen, 
           SerializerProvider provider) throws IOException {
        jgen.writeString("N/A");
    }
}
Run Code Online (Sandbox Code Playgroud)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@interface NAifNull {

}
Run Code Online (Sandbox Code Playgroud)

然后使用如下:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new CustomBeanSerializerModifier());
    }
});
Run Code Online (Sandbox Code Playgroud)