杰克逊特定字段名称

时间:2018-10-15 13:03:32

标签: java jackson jackson-databind

我上了这个课:

@Data
public class DiscountDto {

    @JsonProperty(required = true)
    private DiscountType type;

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

DiscountType是枚举:

public enum  DiscountType {

    PERCENT, AMOUNT
}

我想根据枚举值将discountValue序列化为特定值。如果枚举的值为PERCENT,则必须将DiscountValue序列化为percent_off。如果枚举的值为AMOUNT,则必须将discountValue序列化为amount_off。我怎么可能那样做?

预期结果:

如果类型== AMOUNT,我想要DiscountValue名称= amount_off

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

如果类型== PERCENT,我想要DiscountValue名称= percent_off

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

2 个答案:

答案 0 :(得分:1)

可能的解决方案:

1。创建一个同时具有DiscountType和DiscountValue的构造函数,并直接设置percentOff或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);

答案 1 :(得分:0)

这是如何进行多态性的典型示例。不要误会我的意思,我不是在批评你,这在我们大多数人中已经发生。这是一种内部状态多态性,也就是说,取决于某些属性的值(type甚至名称也说明了,对吗?),其他某些属性的含义有所不同。

要正确解决该问题,您应该在类级别移动属性 type ,每种类型都有一个类。您可以从拥有一个抽象的,无法实例化的类型开始,然后您的特定类型将从中派生。

您可以找到一些示例实现here,以供技术参考。