I have a base class:
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, property = "fieldType", include=JsonTypeInfo.As.EXISTING_PROPERTY, visible=true)
@JsonSubTypes({
@JsonSubTypes.Type(value = JobCurrencyField.class, name = "CURRENCY")
})
public abstract class BaseJobField {
private String name;
private Object value;
private String fieldType;
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
List<BaseJobField> jobFields = new ArrayList<>();
jobFields.add(JobCurrencyField.create("currencyUS", "USD", 10.4));
try {
String fields = objectMapper.writeValueAsString(jobFields);
List<BaseJobField> ret = objectMapper.readValue(fields, new TypeReference<List<BaseJobField>>(){});
JobCurrencyField jobCurrencyField = (JobCurrencyField) ret.get(0);
JobCurrencyField.Currency currency = (JobCurrencyField.Currency)jobCurrencyField.getValue();
} catch (Exception x) {
System.out.println(x.getMessage());
}
}
}
And a subclass:
@Data
@NoArgsConstructor
@JsonTypeName("CURRENCY")
public class JobCurrencyField extends BaseJobField {
@Data
@NoArgsConstructor
public static class Currency {
private String currencyName;
private double amount;
}
public static JobCurrencyField create(String name, String currencyName, Double amount) {
Currency currency = new Currency();
currency.setCurrencyName(currencyName);
currency.setAmount(amount);
JobCurrencyField jobCurrencyField = new JobCurrencyField();
jobCurrencyField.setName(name);
jobCurrencyField.setValue(currency);
jobCurrencyField.setFieldType("CURRENCY");
return jobCurrencyField;
}
}
The unmarshalling of the object, objectMapper.readValue() does not unmarshal the inner class to JobCurrencyField.CURRENCY but to a LinkedHashMap, so:
JobCurrencyField.Currency currency = (JobCurrencyField.Currency)jobCurrencyField.getValue();
throws an exception:
java.util.LinkedHashMap cannot be cast to JobCurrencyField$Currency
How do I tell objectMapper to unmarshal the value to the Currency field instead of a LinkedHashMap?
One way to achieve what you want would be to parameterize the
BaseJobFieldclass asBaseJobField<T>, moveCurrencyclass into its own file and then makeJobCurrencyFieldclass extendBaseJobField<Currency>. The classes ended up looking like below:BaseJobField.java:
Currency.java:
JobCurrencyField.java:
Test to verify the deserialization: