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

时间:2018-06-07 16:44:06

标签: 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);
    }
}

如果注释存在且字段为null,则Witch应该写字符串“N / A”。但是方法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);
}

有了这样的实施:

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();
        }
    }
}

但没有结果。

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

更新

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

prov.setNullValueSerializer(new CustomNullSerializer(annotation));

不应该从CreateContextual方法调用。

2 个答案:

答案 0 :(得分:6)

使用AutoFit特定属性自定义空序列化器:

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;
    }
}

@NAifNullCustomNullSerializer定义如下:

public class CustomNullSerializer extends JsonSerializer<Object> {

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

}

然后按如下方式使用:

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

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new CustomBeanSerializerModifier());
    }
});

答案 1 :(得分:0)

如果我理解正确,您希望将“N / A”写入生成的JSON,如果值为null。

Jackson docs表示值不能为空。这是因为type参数是Class对象,它是constructed automatically by JVM

根据这个article,我认为你可以处理类似

之类的空字段
public class CustomNullSerializer extends StdSerializer<Object> {

   public CustomNullSerializer() {
        this(null);
   }

   public CustomNullSerializer(Class<Object> t) {
        super(t);
   }

   @Override
   public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString("N/A");
   }
}

然后将其与

一起使用
prov.setNullValueSerializer(new CustomNullSerializer());

以为我自己没有尝试过,但我希望它有所帮助。

<强>更新

哎呀,现在我有时间亲自尝试一下。我使用了

ObjectMapper mapper...
mapper.getSerializerProvider().setNullValueSerializer(new CustomNullSerializer());