Jackson - Can the DEDUCTION type take the datatype into account?

Viewed 443

I have the following JSON, where my property can either be a String, a Number or a reference to a variable:

[
  {
    "prop": "string-value"
  },
  {
    "prop": 5
  },
  {
    "prop": {
      "$variable": "var1"
    }
  }
]

I want to deserialize this into 3 subclasses, for this I am trying to use DEDUCTION:

@JsonTypeInfo(use = Id.DEDUCTION)
@JsonSubTypes({ @Type(MultitypeString.class), @Type(MultitypeVariable.class), @Type(MultitypeNumber.class) })
public abstract class Multitype {
}

public class MultitypeString extends Multitype {
    public String value;

    public MultitypeString(String value) {
        this.value = value;
    }
}

public class MultitypeNumber extends Multitype {
    public Number value;

    public MultitypeNumber(Number value) {
        this.value = value;
    }
}

public class MultitypeVariable extends Multitype {
    @JsonIdentityReference
    @JsonProperty("$variable")
    public Variable variable;
}

For the variable reference this works fine but for string and numeric values I get the following error:

Subtypes MultitypeNumber and MultitypeString have the same signature and cannot be uniquely deduced

Which is weird since the signatures do vary, one is a String constructor and one is a Number constructor. Is there a way I can have the DEDUCER take the datatype into account? If not, is there another way to get what I'm trying to achieve?

1 Answers

Let's take a look at documentation for the DEDUCTION field:

Means that no serialized typing-property is used. Types are deduced based on the fields available. Deduction is limited to the names of fields (not their values or, consequently, any nested descendants). Exceptions will be thrown if not enough unique information is present to select a single subtype. If deduction is being used annotation properties visible, property and include are ignored.

It can recognise a type only by a unique field name. Field types are not taken into account.

You can extend default implementation, AsDeductionTypeDeserializer. Take a look at buildFingerprints method, you need to implement another way how to build fingerprints map.

Also, you need to implement proper type handling in deserializeTypedFromScalar method.

Related