All_Safe
All_Safe

Reputation: 1399

Jackson specifc field name

I have this class:

@Data
public class DiscountDto {

    @JsonProperty(required = true)
    private DiscountType type;

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

DiscountType is enum:

public enum  DiscountType {

    PERCENT, AMOUNT
}

I want to serialize the discountValue to a specific value, depending on the Enum value. If enum have value PERCENT, then discountValue must be serialize to percent_off. If enum have value AMOUNT then discountValue must be serialize to amount_off. How could I possibly do that?

Expected result:

If type == AMOUNT, I want discountValue name = amount_off

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

If type == PERCENT, I want discountValue name = percent_off

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

Upvotes: 0

Views: 96

Answers (2)

Adina Rolea
Adina Rolea

Reputation: 2109

Possible solutions:

1.Create a constructor with both DiscountType and discountValue and set directly the value of the percentOff or amountOff field:

@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.Use a custom JSON serializer:

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

and your ObjectMapper should have this new serializer:

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

Upvotes: 1

NiVeR
NiVeR

Reputation: 9786

This is a typical example of how not to do polymorphism. Don't get me wrong, I am not crticizing you, this has happend to most of us. This is a sort of inner-state polymorphism, that is, depending on the value of some property (type even the name says it, right?) some other property gets a different meaning.

To solve the problem correctly, you should move the poperty type, at the level of the class, having a class for each type. You can start by having an abstract, uninstantiable type, and your specific types will derive from it.

You can find some sample implementation here, for technical reference.

Upvotes: 0

Related Questions