【问题标题】:Jackson deserialization interface on multiple types多种类型的杰克逊反序列化接口
【发布时间】:2021-09-09 05:52:09
【问题描述】:

我正在用 Java 中的 Jackson 反序列化试验一些麻烦。我已经提出了2个解决方案,但我无法解决问题。问题?我得到了属性重复的结果,这是在杰克逊反序列化后重复的字段。 (我的问题和这个问题一模一样:Avoid duplicate field generated by JsonTypeInfo in Jackson,当时没人能给你答案)

首先,我有以下课程:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Instance {

    @JsonProperty("id")
    private String id;
 
    @JsonProperty("name")
    private String name;

    @JsonProperty("type")
    private InstanceType type;
 }

我想做的只是实例化一个'Instance'类型的对象,保存并阅读它。使用解决方案 2,对象以重复的类型保存(类型显示为包含“name”、“firs_type”或“second_type”的数组)取决于我创建的内容。使用解决方案 1,我可以保存对象,但是当我尝试读取它时,我遇到了杰克逊异常投射。

解决方案 1:

@JsonDeserialize(using = InstanceTypeDeserializer.class)
public interface InstanceType {
    String value();
}

@JsonDeserialize(as = HardInstanceType.class)
public enum HardInstanceType implements InstanceType {
    FIRST_TYPE("first_type"),
    SECOND_TYPE("second_type")
    private String value;

    HardInstanceType(String value) {
        this.value = value;
    }

    @JsonValue
    public String value() {
       return value;
    }
}

@JsonDeserialize(as = SoftInstanceType.class)
public enum SoftInstanceType implements InstanceType {
    //.. types implementaion similar as HardInstanceType
}

public class InstanceTypeDeserializer extends JsonDeserializer<InstanceType> {
    @Override
    public InstanceType deserialize(JsonParser jp,  DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        ObjectNode root = (ObjectNode) mapper.readTree(jp);
        
        if(root.get("name").asText().equals("hard")) {
            return mapper.readValue(root.toString(), HardInstanceType.class);
        } else { 
            return mapper.readValue(root.toString(), SoftInstanceType.class);
        }
    }
}

此解决方案的问题在于,当我尝试获取存储的数据并映射到类时,出现以下错误:

异常解析json: com.fasterxml.jackson.databind.JsonMappingException:类 com.fasterxml.jackson.databind.node.TextNode 无法转换为类 com.fasterxml.jackson.databind.node.ObjectNode (com.fasterxml.jackson.databind.node.TextNode 和 com.fasterxml.jackson.databind.node.ObjectNode 在未命名的模块中 加载器 org.springframework.boot.loader.LaunchedURLClassLoader @1a3e8e24)(通过参考链: java.util.ArrayList[0]->com.project.package.xxxx.Instance["type"])

解决方案 2

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "name")
@JsonSubTypes({
    @JsonSubTypes.Type(value = HardInstanceType.class, name = "hard") })
public interface InstanceType {
   String value();
}

这个解决方案的问题是,当我保存数据时,当我创建一个实例对象并将其存储在存储的数据中时,我得到以下信息:

      "id": "1",
      "name": "hard",
      "type": [
        "hard",
        "first_type"
      ]

什么不正确,类型应该只存储“first_type”(与解决方案1一起存储的内容,但我看不懂哈哈)。

当然,Instace 类比较复杂,字段也比较多,这里我把它简化了,只是为了举例。

我需要这方面的帮助,非常感谢您。

【问题讨论】:

  • 如果问题陈述在顶部而不是在中间,它可能会得到更多关注。
  • 请提及您尝试使用解决方案 1 和解决方案 2 保存的一些 JSON 数据

标签: java json jackson deserialization json-deserialization


【解决方案1】:

终于,我可以解决问题了。 我发布这个以防其他人需要它。

  1. 向我的 HardInstanceType 类添加一个属性。

    公共枚举 HardInstanceType 实现 InstanceType {

      FIRST_TYPE("first_type"),
      SECOND_TYPE("second_type");
      private String value;
    
      public String hardTypeIdentifierSer = "hardTypeIdentifierSer";
    
      HardInstanceType(String value) {
          this.value = value;
      }
    
      @JsonValue
      public String value() {
         return value;
      }
    

    }

  2. 然后,在反序列化器中:

    公共类 InstanceTypeDeserializer 扩展 JsonDeserializer {

     @Override
     public InstanceType deserialize(JsonParser jp,  DeserializationContext ctxt) throws IOException, JsonProcessingException {
         TreeNode node = jp.readValueAsTree();
    
         if (node.get("hardTypeIdentifierSer") != null) {
             return jp.getCodec().treeToValue(node, HardInstanceType.class);
         }
    

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 2018-10-14
    • 2015-05-13
    相关资源
    最近更新 更多