【问题标题】:How do I deserialize a JSON object onto an implementation of an interface based on its key-value pairs?如何根据键值对将 JSON 对象反序列化到接口的实现上?
【发布时间】:2018-12-29 08:41:03
【问题描述】:

我正在为 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;

}

(注意:如果提供了重量,则为杂货,不能为空或“”。如果未提供重量,则为服装)。

控制器

@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 个端点来处理每种情况会更容易。

【问题讨论】:

    标签: java json spring-boot jackson


    【解决方案1】:

    您可以通过添加静态工厂方法来实现 (带有@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 时使用该方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多