【问题标题】:Jackson: How to deserialize json with shorthand property valueJackson:如何使用速记属性值反序列化 json
【发布时间】:2015-06-02 14:51:48
【问题描述】:

我正在努力找出如何使用 Jackson 将使用简写约定的 JSON 反序列化为 Java POJO。

[
  { 
    "id":1,
    "type": "simple"
  },
  { 
    "id":2,
    "type": { "kind": "simple" }
  },
  { 
    "id":3,
    "type": {
      "kind": "complex",
      "someOtherThing": "value"
    }
  }
]

这里的“type”属性可以是字符串也可以是对象。如果它是一个字符串,那么它被认为是具有默认属性的同一对象的简单速记形式。 IE。上例中的 1 和 2 是等价的。

据我了解,可以为整个“类型”对象编写自定义反序列化程序。据我了解,在这种情况下,我将不得不手动反序列化整个“类型”对象。但我真的只想手动处理速记形式并将正常处理委托给基于注释的映射器。这可能吗?

【问题讨论】:

    标签: java json jackson deserialization


    【解决方案1】:

    您可以简单地定义一个带有参数的构造函数,它将创建具有简单类型的对象。在您的情况下,您的 Type 类将有一个 String 构造函数。不要忘记包含一个 noargs 构造函数。

    public static void main(String [] args) throws JsonParseException, JsonMappingException, IOException {
        String str = "[ {\"id\":1,\"type\":\"simple\" }, {\"id\":2,\"type\": {\"kind\":\"simple\" } }, {\"id\":3,\"type\": {\"kind\":\"complex\",\"someOtherThing\":\"value\" } }]";
        ObjectMapper mapper = new ObjectMapper();
        MyObject[] objs = mapper.readValue(str.getBytes(), MyObject[].class);
        for(MyObject obj : objs) {
            System.out.println(obj.id + " " + obj.type.kind + " " + obj.type.someOtherThing);
        }
    }
    
    public static class MyObject {
        public String id;
        public Type type;
    }
    
    public static class Type {
        public String kind;
        public String someOtherThing;
    
        public Type() {
        }
    
        public Type(String kind) {
            this.kind = kind;
        }
    }
    

    打印出来

    1 simple null
    2 simple null
    3 complex value
    

    【讨论】:

      【解决方案2】:

      您可能需要为type 编写自定义BeanDeserializer 子类。但是,您可以利用 Jackson 的其余部分来处理类型对象。

      您最好的选择是@JsonIgnore 对象中的类型属性。然后,在自定义反序列化器中,覆盖handleIgnoredProperty()。在这个方法中,做这样的事情:

      protected void handleIgnoredProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName)
              throws IOException, JsonProcessingException {
        if ("type".equals(propName)) {
           if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
             MyObjectDeserializer myObjectDeserializer = (MyObjectDeserializer) ctxt.findRootValueDeserializer(ctxt                   .getTypeFactory().constructType(MyObject.class));
             MyObject myObject = (MyObject) myObjectDeserializer.deserialize(jp, ctxt);
             // cast beanOrClass to your object and call object.setType(myObject)
           }
           else {
              // get a StringDeserializer and call object.setType(string)
           }
        }
        else {
          super.handleIgnoredProperty(jp, ctxt, beanOrClass, propName);
        }
      }
      

      您可能需要进行更多处理以手动读取带有 jp.nextToken() 的 kind 值以到达 someOtherThing 但我希望这足以让您开始。

      【讨论】:

        猜你喜欢
        • 2012-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-09
        • 2017-01-31
        • 2020-01-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多