0

I'm trying to manage different value structure using polimorphism. The next example contains 2 jsons that should be deserialized into the same parent object

 {
   "maximum": {
     "type": "type1",
     "value": {
       "USD": 1000000,
       "GBP": 500000
     }
   }
 }

 {
   "maximum": {
     "type": "type2",
     "linkedTo": "linked to item",
     "value": 2
   }
 }

I have defined the next classes to manage that:

@JsonInclude (Include.NON_EMPTY)
@JsonDeserialize (builder = Parent.Builder.class)
public class Parent {
  private ParentType maximum;

  private Parent(Builder builder) {
    this.maximum = builder.maximum;
  }

  public static Builder builder() { return new Builder(); }

  public ParentType getMaximum() {
    return maximum;
  }

  public static class Builder {
    private ParentType maximum;

    public Builder withMaximum(final ParentType maximum) {
      this.maximum = maximum;
      return this;
    }

    public Parent build() {
      return new Parent(this);
    }
  }
}

@JsonInclude (Include.NON_EMPTY)
@JsonDeserialize (builder = ParentType.Builder.class)
public class ParentType {

  private String type;
  private String linkedTo;
  private ParentTypeValue value;

  private ParentType(Builder builder) {
    this.type = builder.type;
    this.linkedTo = builder.linkedTo;
    this.value = builder.value;
  }

  public static Builder builder() { return new Builder(); }

  public String getType() {
    return type;
  }

  public String getLinkedTo() {
    return linkedTo;
  }

  public ParentTypeValue getValue() {
    return value;
  }

  public static class Builder {
    private String type;
    private String linkedTo;
    private ParentTypeValue value;

    public Builder withType(final String type) {
      this.type = type;
      return this;
    }

    public Builder withLinkedTo(final String linkedTo) {
      this.linkedTo = linkedTo;
      return this;
    }

    public Builder withValue(final ParentTypeValue value) {
      this.value = value;
      return this;
    }

    public ParentType build() {
      return new ParentType(this);
    }
  }
}

And finally I tried the polymorphism of Value with the next structure:

@JsonSubTypes ({
  @JsonSubTypes.Type(value = CurrencyMapValue.class, name = "currencymapType"),
  @JsonSubTypes.Type(value = StringValue.class, name = "integerType"),
})
public abstract class ParentTypeValue {

}

@JsonTypeName ("integerType")
public class IntegerValue extends ParentTypeValue {
  private int value;

  private IntegerValue(Builder builder) {
    this.value = builder.value;
  }

  public static Builder builder() { return new Builder(); }

  public int getValue() {
    return value;
  }

  public static class Builder {
    private int value;

    public Builder withValue(final int value) {
      this.value = value;
      return this;
    }

    public IntegerValue build() {
      return new IntegerValue(this);
    }
  }
}

@JsonTypeName ("currencymapType")
public class CurrencyMapValue extends LimitTypeValue {
  private Map<Currency, Double> value;

  private CurrencyMapValue(Builder builder) {
    this.value = builder.value;
  }

  public static Builder builder() { return new Builder(); }

  public Map<Currency, Double> getValue() {
    return value;
  }

  public static class Builder {
    private Map<Currency, Double> value;

    public Builder withValue(final Map<Currency, Double> value) {
      this.value = value;
      return this;
    }

    public CurrencyMapValue build() {
      return new CurrencyMapValue(this);
    }
  }
}

I'm guessing the polymorphic structure is wrong as I'm not able to deserialize and serialize is adding an extra value object inside the wanted value. I mean something like that:

  "maximum": {
    "type": "amount",
    "linkedTo": "linkedTo",
    "value": {
      **"value": {**
        "USD": 5000000,
        "GBP": 200000
      }
    }
  }

Does anyone have an idea about what is wrong on that?. I appreciate very much your help!

Luismi
  • 1
  • 1

1 Answers1

0

Try this..

Please note that @JsonSubTypes and @JsonTypeInfo annotations are added inside Maximum class.

You dont need @JsonTypeName annotation in your CurrencyMapValue and IntegerValue classes if you are only de-serializing. Yet I have added them.

public abstract class ParentTypeValue {}
@Getter
@Builder
@JsonDeserialize(builder = CurrencyMapValue.CurrencyMapValueBuilder.class)
@JsonTypeName("type1")
public class CurrencyMapValue extends ParentTypeValue {
    private Map<String, Double> value;

    @JsonPOJOBuilder(withPrefix="")
    public static class CurrencyMapValueBuilder {}
}
@Getter
@Builder
@JsonDeserialize(builder = IntegerValue.IntegerValueBuilder.class)
@JsonTypeName("type2")
public class IntegerValue extends ParentTypeValue {
    private int value;
    private String linkedTo;

    @JsonPOJOBuilder(withPrefix="")
    public static class IntegerValueBuilder {}
}
@Getter
@Setter
public class Maximum {
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = CurrencyMapValue.class, name = "type1"),
            @JsonSubTypes.Type(value = IntegerValue.class, name = "type2"),
    })
    private ParentTypeValue maximum;
}
ray
  • 1,512
  • 4
  • 11