У меня есть структура данных, которая имеет специальное свойство. Структура данных представляет данные о ценах на акции за весь день. [Так что в основном OLHC] В моей текущей процедуре сериализации и построителе я в настоящее время поддерживаю свойство "все". Каков метод в построителе, который устанавливает все цены OHLC по одной цене.
Есть ли способ установить это без необходимости иметь имя свойства для всех?
Возможно ли это в Джексоне?
Пример:
Структура данных выглядит так:
EODPrice
- Open
- Low
- Close
- High
Давайте скажем, что у нас есть json: " {all: 5.00}
" Это будет десериализовать, чтобы открыть: 5.00, минимум: 5.00, закрытие: 5.00 и максимум: 5.00. Если бы мы сериализовались, я бы хотел изменить поведение, так что если у нас есть Open == Low == Close == High, мы бы создали одно свойство, называемое all. Если это условие было неверным, мы бы не сериализовали свойство "все" вообще.
Сериализационная часть, безусловно, возможна, используя аннотацию @JsonFilter
которой вы можете прочитать в документации Джексона.
Deserialization является стандартным Джексоном с помощью @JsonCreator
.
Фильтры могут применяться к классам, методам и полям, и вы можете написать собственный собственный фильтр, который обрабатывает проблему с открытыми, низкими, закрытыми и большими.
Проверьте этот учебник для отличного введения.
Для примера кода взгляните на это. Сначала объявите свою EODPrice
с @JsonFilter
аннотации @JsonFilter
.
@JsonIgnoreProperties(ignoreUnknown = true) // required to skip the "all" attribute in the JSON
@JsonFilter("allFilter") // Specify the filter
public class EODPrice {
private final BigDecimal close;
private final BigDecimal high;
private final BigDecimal low;
private final BigDecimal open;
// Builder method, does not include "all"
@JsonCreator
public EODPrice(
@JsonProperty("open") final BigDecimal open,
@JsonProperty("low") final BigDecimal low,
@JsonProperty("close") final BigDecimal close,
@JsonProperty("high") final BigDecimal high) {
this.open = open;
this.low = low;
this.close = close;
this.high = high;
}
// This is not part of the JSON but puts the business logic in the POJO
@JsonIgnore
public boolean allFieldsEqual() {
return open.equals(low) && open.equals(close) && open.equals(high);
}
public BigDecimal getAll() {
if (allFieldsEqual()) {
return open;
}
return BigDecimal.ZERO;
}
public BigDecimal getClose() {
return close;
}
public BigDecimal getHigh() {
return high;
}
public BigDecimal getLow() {
return low;
}
public BigDecimal getOpen() {
return open;
}
}
Фильтр может выглядеть примерно так:
private PropertyFilter allFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField(
Object pojo,
JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {
// If it is not the "all" property, go on with normal serialization
if (!writer.getName().equals("all")) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
// Else, check the special all-rule
final EODPrice eodPrice = (EODPrice) pojo;
if (eodPrice.allFieldsEqual()) {
// Only serialize if all fields are equal
writer.serializeAsField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
Наконец, настройте карту. Этот тест показывает, что фильтр срабатывает:
@Test
public void testJsonRoundtrip() throws IOException {
final FilterProvider filters = new SimpleFilterProvider().addFilter("allFilter", allFilter);
final EODPrice eodPriceWithAll = new EODPrice(BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE);
final EODPrice eodPriceWithoutAll = new EODPrice(BigDecimal.TEN, BigDecimal.ONE, BigDecimal.ONE, BigDecimal.ONE);
final ObjectMapper mapper = new ObjectMapper();
mapper.setFilters(filters);
// First, test serialization
final String eodWithAllAsStr = mapper.writeValueAsString(eodPriceWithAll);
final String eodWithoutAllAsStr = mapper.writeValueAsString(eodPriceWithoutAll);
Assert.assertTrue(eodWithAllAsStr.contains("all"));
Assert.assertFalse(eodWithoutAllAsStr.contains("all"));
// Then, test deserialization
final EODPrice eodPriceWithAll2 = mapper.readValue(eodWithAllAsStr, EODPrice.class);
final EODPrice eodPriceWithoutAll2 = mapper.readValue(eodWithoutAllAsStr, EODPrice.class);
Assert.assertTrue(eodPriceWithAll2.allFieldsEqual());
Assert.assertFalse(eodPriceWithoutAll2.allFieldsEqual());
}
EDIT: После обновления от десериализации OP добавляется обновление POJO. Кроме того, бизнес-логика перемещается из фильтра в POJO.
all
свойства будут сериализованы / десериализованы? Какое сравнение вы упоминаете?