我正在为Spring Boot应用程序设置一个控制器。我希望控制器根据传入的JSON字符串的键值对生成接口实现的实例。
界面:
public interface ShoppableItem {}
实现1:
public class GroceryItem implements ShoppableItem {
@JsonProperty("transactionId")
private Long transactionId;
@JsonProperty
@NotNull
private String itemName;
@JsonProperty
@NotNull
private Float weight;
}
实施2:
public class ClothingItem implements ShoppableItem {
@JsonProperty("transactionId")
private Long transactionId;
@JsonProperty
@NotNull
private String itemName;
}
(注意:如果提供了重量,则为杂货,并且不能为null或“”。如果没有提供重量,则为服装)。
控制器
@Controller
public class Total {
@PostMapping(value = "total")
@ResponseStatus(HttpStatus.ACCEPTED)
public String tester(@Valid @RequestBody ShoppableItem shoppableItem) {
return shoppableItem.toString();
}
}
JSON正文
{
"transactionId" : "123",
"itemName" : "whatever"
}
所需结果是创建一个ClothingItem类型的实例。当我尝试执行此操作时,出现以下异常:
org.springframework.http.converter.HttpMessageNotReadableException:JSON解析错误:无法构造com.test.controllers.Models.ShoppableItem的实例:抽象类型要么需要映射到具体类型,要么具有自定义反序列化器,或者包含其他类型类型信息;嵌套异常是com.fasterxml.jackson.databind.JsonMappingException:无法构造com.test.controllers.Models.ShoppableItem的实例:抽象类型要么需要映射到具体类型,要么具有自定义反序列化器,或者包含其他类型信息>
这是我执行不正确的功能吗?我知道这可能不是最好的方法,因为仅创建2个端点来处理每种情况会更容易。
答案 0 :(得分:0)
您可以通过添加静态工厂方法来实现
(用@JsonCreator
注释)到ShoppableItem
界面。
请注意,您需要使用@JsonProperty
注释其所有参数。
这样Jackson就会知道如何将JSON属性映射到方法参数。
public interface ShoppableItem {
@JsonCreator
public static ShoppableItem create(@JsonProperty("transactionId") Long transactionId,
@JsonProperty("itemName") String itemName,
@JsonProperty("weight") Float weight) {
if (weight == null)
return new ClothingItem(transactionId, itemName);
else
return new GroceryItem(transactionId, itemName, weight);
}
}
然后,杰克逊在反序列化ShoppableItem
时将使用该方法。