如何根据JSON对象的键值对将其反序列化到接口的实现上



我正在为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.coverter.HttpMessageNotReadableException:JSON解析错误:无法构造com.test.controllers.Models.HoppableItem的实例:抽象类型要么需要映射到具体类型,要么需要自定义反序列化程序,要么包含其他类型信息;嵌套异常为com.fasterxml.jackson.databind.JsonMappingException:无法构造com.test.controllers.Models.HoppableItem的实例:抽象类型需要映射到具体类型、具有自定义反序列化程序或包含其他类型信息

这是我错误实现的功能吗?我知道这可能不是最好的方法,因为只创建2个端点来处理每个案例会更容易。

您可以通过添加静态工厂方法来实现这一点(用@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);
}
}

然后Jackson将在反序列化ShoppableItem时使用该方法。

最新更新