假设我们有以下课程:
public abstract class Investment {
private String investmentType;
// getters & setters
}
public class Equity extends Investment {
}
public class Bond extends Investment {
}
public class InvestmentFactory {
public static Investment getTypeFromString(String investmentType) {
Investment investment = null;
if ("Bond".equals(investmentType)) {
investment = new Bond();
} else if ("Equity".equals(investmentType)) {
investment = new Equity();
} else {
// throw exception
}
return investment;
}
}
以及以下
@RestController
:@RestController
public class InvestmentsRestController {
private InvestmentRepository investmentRepository;
@Autowired
public InvestmentsRestController(InvestmentRepository investmentRepository) {
this.investmentRepository = investmentRepository;
}
@RequestMapping(RequestMethod.POST)
public List<Investment> update(@RequestBody List<Investment> investments) {
return investmentRepository.update(investments);
}
}
以及请求正文中的以下json:
[
{"investmentType":"Bond"},
{"investmentType":"Equity"}
]
如何在抽象类
List<Investment>
上不使用Jackson的@JsonSubTypes
的情况下,将json绑定或转换为Investment
的请求正文,而使用InvestmentFactory
呢? 最佳答案
@JsonDeserialize的效果很好,但是如果您除了类型以外还有更多的字段,则必须手动设置它们。如果您要回到 jackson ,可以使用:
投资类
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "investmentType")
@JsonTypeIdResolver(InvestmentResolver.class)
public abstract class Investment {
}
InvestmentResolver.class
public class InvestmentResolver extends TypeIdResolverBase {
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
Investment investment = InvestmentFactory.getTypeFromString(type);
return context.constructType(investment.getClass());
}
这样做的好处是,如果您开始向“投资”中添加字段,则不必在Desrializer中添加它们(至少在我的情况下是这样),但 jackson 会为您处理。因此,明天您可以拥有测试用例:
'[{"investmentType":"Bond","investmentName":"ABC"},{"investmentType":"Equity","investmentName":"APPL"}]'
你应该很好走!