【问题标题】:Deserialization of dynamic attribute of JSON entity using Jackson使用Jackson反序列化JSON实体的动态属性
【发布时间】:2019-08-13 20:14:55
【问题描述】:

存在具有value动态属性的JSON实体:

   {
    "name" : "name1",
    "value" : {"different structures: strings, enums, arrays, custom entities"}
   }

实体的Java表示:

public class Entity {
    public String name;
    public Object value;
}

在value 中可以传递完全不同的JSON 结构。每次value都应该映射到不同的POJO。

除了对value 属性内容(Map<String, String> 结构)的额外反序列化之外,是否有任何通用方法可以将 value 属性反序列化为特定实体?

【问题讨论】:

    标签: java json jackson deserialization json-deserialization


    【解决方案1】:

    我使用@JsonSubTypes(序列化为不同类型)或@JsonDeserialize(自定义序列化)来执行此操作。你可以在https://www.baeldung.com/jackson-annotations看到一些例子

    【讨论】:

    • 但是@JsonSubTypes 不适合没有共同层次结构的完全不同的类。
    • 您的回答帮助我找到正确的解决方案。谢谢
    【解决方案2】:

    您始终可以将任何有效的 JSON 文档反序列化为 Map<String, Object> 类,您不必进行“额外”反序列化。只需将您的 public Object value; 更改为 public Map<String, Object> value; 即可。

    【讨论】:

    • 我完全同意这个解决方案有效,但在这种情况下,我应该在反序列化后将Map<String, Object> value 映射到我的服务器端模型。我想以某种方式把这个责任转移给杰克逊。
    • 因此,您将 Entity 类更改为具有 Map 的值,并将 Entity 类作为服务器端端点方法的参数。然后你将你的 JSON 发送到你的服务器端,它会自动反序列化到你的实体类中。然后你在你的服务器端有你的实体类实例。我错过了什么吗?
    • 但我不明白将可以包含不同类型的value 反序列化到给定模型中有何帮助?反序列化后它将是Map<String, Object>,但我想在value 属性中获取Integer 或Boolean 或一些自定义实体。
    【解决方案3】:

    为了知道我应该反序列化的确切类型value,应该添加新属性valueType。 此外,应实现自定义反序列化器以处理反序列化为所需类型。

    Entity 类扩展了valueType 和@JsonDeserialize 注释:

    public class Entity {
        public String name;
        @JsonDeserialize(using = EntityValueDeserializer.class)
        public Object value;
        public Class valueType;
    }
    

    JSON 相应改变:

       {
        "name" : "name1",
        "value" : "some string" | 10 | "any custom entity",
        "valueType" : "java.lang.String" | "java.lang.Integer" | "any custom type"
       }
    

    然后实现自定义反序列化器EntityValueDeserializer 得到valueType 并将value 反序列化为valueType:

    public class EntityValueDeserializer extends JsonDeserializer<Object>
    {
    
       public Object deserialize(JsonParser jp, DeserializationContext ctx) throws IOException
       {
          ObjectCodec codec = jp.getCodec();
          JsonNode node = codec.readTree(jp);
          Entity entity = ((Entity) jp.getParsingContext().getCurrentValue());
          return codec.treeToValue(node, entity.valueType);
       }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多