如何通过注释有条件地使用自定义JsonSerializer

时间:2018-09-09 05:18:36

标签: java json spring jackson

我已经编写了一个自定义的 JsonSerializer ,用于将BigDecimal转换为String。我想使用 @JsonSerialize 注释来调用此序列化程序,但有条件地,即,如果特定的布尔值仅为true,则应执行从BigDecimal到String的转换。

我有一个POJO,其中有一个BigDecimal price 字段。发送此P​​OJO是为了响应两个剩余调用:

  • 期望价格字段为数值// // @ JsonSerialize应该 不运行
  • 期望价格字段为字符串值// so @JsonSerialize 应该运行

有人可以建议我如何实现吗?

以下是我编写的自定义序列化程序的代码段:

public class BigDecimalToStringSerializer extends JsonSerializer<BigDecimal> {

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException,
        JsonProcessingException {
        gen.writeString(value.toString());
    }

}

具有价格字段的POJO文件:

JsonInclude(Include.NON_NULL)
public class Price{
    private BigDecimal price;
    public Price() {
    }
    @JsonSerialize(using = BigDecimalToStringSerializer.class)
    public BigDecimal getPrice() {
        return price;
    }   
    public void setPrice(BigDecimal pric) {
        this.price  = price;
    }
}

提前感谢一吨!!

3 个答案:

答案 0 :(得分:3)

您可以为此实现PropertyFilter。首先,您需要使用@JsonFilter批注在我们的实体上定义过滤器:

@JsonFilter("stringValueFilter")
public class Price {
  private BigDecimal price;
  public Price() {
  }

  public BigDecimal getPrice() {
     return price;
  }   
  public void setPrice(BigDecimal pric) {
     this.price  = price;
  }
}

这是您的PropertyFilter

public interface PropertyFilter {
    void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer);

    void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception;

    void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException;

    @Deprecated 
    void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException;
}

第一种方法需要针对您的情况的特殊实现:

public class StringValueFilter implements PropertyFilter {
    void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) {
        if (pojo instanceof Price && isValueFieldNumber((Price) pojo)) {
            return; // skip this field
        }
        writer.serializeAsField(pojo, jgen, prov);
    }

    private isValueFieldNumber(Price price) {
        return: //check your logic and return
     }

    void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
        writer.serializeAsField(elementValue, jgen, prov);
    }

    void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException {
        writer.depositSchemaProperty(objectVisitor);
    }

    @Deprecated 
    void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException {
        writer.depositSchemaProperty(propertiesNode, provider);
    }
}

此过滤器包含实际逻辑,根据其值确定price字段是否要序列化。

接下来,您需要将此过滤器连接到ObjectMapper

final ObjectMapper mapper = new ObjectMapper();
final FilterProvider filterProvider = new SimpleFilterProvider()
        .addFilter("stringValueFilter", new StringValueFilter());
mapper.setFilters(filterProvider);

答案 1 :(得分:2)

唯一的更改是自定义序列化程序类中所需的

public class BigDecimalToStringSerializer extends JsonSerializer<BigDecimal> {

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException,
        JsonProcessingException {
    if (pojo instanceof Price && ((Price) pojo).shouldConvertInString()) {
        gen.writeString(value.toString());
    } else {
        gen.writeNumber(value);
    }
    }

}

答案 2 :(得分:1)

1。在您的价格类上放置@JsonFilter:

@JsonFilter("myFilter")
@JsonInclude(Include.NON_NULL)
public class Price {
    private BigDecimal price;
    public Price() {}
    @JsonSerialize(using = BigDecimalToStringSerializer.class)
    public BigDecimal getPrice() {
        return price;
    }
    public void setPrice(BigDecimal pric) {
        this.price = price;
    }
}

2。定义CustomFilter逻辑

  

检查字段是否为“价格”:
  如果没有,请正常序列化并返回<​​br/>   如果是这样,请检查您的布尔值字段以查看是否需要序列化

    public class CustomFilter extends SimpleBeanPropertyFilter {
    @Override
    public void serializeAsField
        (Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
    throws Exception {
        if (include(writer)) {
            if (!writer.getName().equals("price")) {
                writer.serializeAsField(pojo, jgen, provider);
                return;
            }
            Boolean toSerializeOrNot = ((MyDtoWithFilter) pojo).getYourCoditionalField();
            if (toSerializeOrNot) {
                writer.serializeAsField(pojo, jgen, provider);
            }
        } else if (!jgen.canOmitFields()) { 
            writer.serializeAsOmittedField(pojo, jgen, provider);
        }
    }
    @Override
    protected boolean include(BeanPropertyWriter writer) {
        return true;
    }
    @Override
    protected boolean include(PropertyWriter writer) {
        return true;
    }
}

更多信息

https://www.baeldung.com/jackson-serialize-field-custom-criteria