我有一个基类:
@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());
}
}
}
还有一个子类:
@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;
}
}
对象的解组,
objectMapper.readValue()
不会将内部类解组为JobCurrencyField.CURRENCY,而是解组为LinkedHashMap,因此:
JobCurrencyField.Currency currency = (JobCurrencyField.Currency)jobCurrencyField.getValue();
java.util.LinkedHashMap cannot be cast to JobCurrencyField$Currency
实现您想要的效果的一种方法是将
BaseJobField
类参数化为 BaseJobField<T>
,将 Currency
类移动到其自己的文件中,然后使 JobCurrencyField
类扩展 BaseJobField<Currency>
。课程最终如下所示:
BaseJobField.java:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@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<T> {
private String name;
private T value;
private String fieldType;
}
Currency.java:
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Currency {
private String currencyName;
private double amount;
}
JobCurrencyField.java:
import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@JsonTypeName("CURRENCY")
public class JobCurrencyField extends BaseJobField<Currency> {
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;
}
}
测试验证反序列化:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.List;
import java.util.ArrayList;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class JacksonTest {
@Test
public void testDeserialize() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
List<BaseJobField<?>> jobFields = new ArrayList<>();
jobFields.add(JobCurrencyField.create("currencyUS", "USD", 10.4));
String fields = objectMapper.writeValueAsString(jobFields);
List<BaseJobField<?>> ret = objectMapper.readValue(fields, new TypeReference<List<BaseJobField<?>>>(){});
JobCurrencyField jobCurrencyField = (JobCurrencyField) ret.get(0);
Currency currency = (Currency)jobCurrencyField.getValue();
Assertions.assertTrue(currency instanceof Currency);
Assertions.assertEquals("USD", currency.getCurrencyName());
Assertions.assertEquals(10.4d, currency.getAmount());
}
}