Джексон указывает имя поля - PullRequest
0 голосов
/ 15 октября 2018

У меня есть этот класс:

@Data
public class DiscountDto {

    @JsonProperty(required = true)
    private DiscountType type;

    @JsonProperty(required = true)
    private double discountValue;
}

DiscountType - это enum:

public enum  DiscountType {

    PERCENT, AMOUNT
}

Я хочу сериализовать discountValue до определенного значения, в зависимости от значения Enum.Если enum имеет значение PERCENT, то discountValue должно быть сериализовано в percent_off.Если enum имеет значение AMOUNT, то discountValue должен быть сериализован в amount_off.Как я мог это сделать?

Ожидаемый результат:

Если type == AMOUNT, я хочу, чтобы имя discountValue = amount_off

"discountDto": {
    "amount_off": "11.0",
    "type": "AMOUNT"
}

Есливведите == ПРОЦЕНТ, я хочу имя скидки_значение = процент_офф

"discountDto": {
    "percent_off": "11.0",
    "type": "PERCENT"
}

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Это типичный пример того, как не делает полиморфизм.Не поймите меня неправильно, я не критикую вас, это произошло с большинством из нас.Это своего рода полиморфизм внутреннего состояния, то есть в зависимости от значения какого-либо свойства (type даже имя говорит об этом, верно?), Какое-то другое свойство приобретает другое значение.

Чтобы правильно решить проблему, вы должны переместить poperty type на уровень класса, имея класс для каждого типа.Вы можете начать с наличия абстрактного, не поддающегося объяснению типа, и из него будут получены ваши конкретные типы.

Вы можете найти пример реализации здесь , для технической справки.

0 голосов
/ 15 октября 2018

Возможные решения:

1.Создайте конструктор с DiscountType и discountValue и установите непосредственно значение поля процентаOff или amountOff:

@JsonInclude(Include.NON_NULL)
public class DiscountDto {

     private DiscountType type;

     @JsonProperty("percent_off")
     private Double percentOff;

     @JsonProperty("amount_off")
     private Double amountOff;

     public DiscountDto(DiscountType type, double discountValue){
          this.type = type;
          if(type.equals(DiscountType.PERCENT)){
              this.percentOff = discountValue;
          }else {
              this.discountOff = discountValue;
          }

     }
     //getters and setters
}

2. Используйте пользовательский сериализатор JSON:

public class DiscountDtoSerializer extends StdSerializer<DiscountDto> {

    public DiscountDtoSerializer() {
        this(null);
    }

    public DiscountDtoSerializer(Class<DiscountDto> t) {
        super(t);
    }

    @Override
    public void serialize(DiscountDto value, JsonGenerator jgen, SerializerProvider provider)
      throws IOException, JsonProcessingException {

        jgen.writeStartObject();
        jgen.writeNumberField("type", value.getDiscountType());
        if(value.getDiscountType().equals(DiscountType.PERCENT)){
            jgen.writeStringField("percent_off", value.getDiscountValue());
        }else{
            jgen.writeStringField("amount_off", value.getDiscountValue());
        }
        jgen.writeEndObject();
    }
 }

и ваш ObjectMapper должен иметь этот новый сериализатор:

 ObjectMapper mapper = new ObjectMapper();
 SimpleModule module = new SimpleModule();
 module.addSerializer(DiscountDto.class, new DiscountDtoSerializer());
 mapper.registerModule(module);
...