Как использовать пользовательский JsonSerializer условно с помощью аннотации - PullRequest
0 голосов
/ 09 сентября 2018

Я написал пользовательский JsonSerializer для преобразования BigDecimal в String. Я хочу вызвать этот сериализатор, используя аннотацию @ JsonSerialize , но условно, т. Е. Если конкретное логическое значение истинно только тогда, то это преобразование BigDecimal в String должно быть выполнено, иначе нет.

У меня есть POJO с полем BigDecimal цена . Этот POJO отправляется в ответ на два остальных звонка:

  • ожидает поле цены как числовое значение // поэтому @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 голосов
/ 09 сентября 2018

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

Проверьте, является ли поле "цена":
если нет, сериализуйте нормально и верните
если так, проверьте ваше логическое поле, чтобы увидеть, если вы должны сериализовать или нет

    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

0 голосов
/ 11 сентября 2018

В пользовательском классе сериализатора требуется только изменение:

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

}

0 голосов
/ 09 сентября 2018

Вы можете реализовать 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...