如何委托杰克逊的自定义反序列化器中的默认反序列化?

时间:2016-01-05 21:35:03

标签: java json serialization jackson

假设我正在为某个类编写自定义序列化,但希望使用默认方法处理其中一个字段。

怎么做?

序列化时我们有JsonGenerator#writeObjectField()

但反序列化的对应方法是什么?

请注意以下代码:

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.IOException;
import java.util.Objects;

public class TryDelegate {

   public static class MyOuterClassSerializer extends JsonSerializer<MyOuterClass> {

      @Override
      public void serialize(MyOuterClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
         gen.writeStartObject();

         gen.writeObjectField("inner", value.getInner());

         gen.writeEndObject();
      }
   }

   public static class MyOuterClassDeserializer extends JsonDeserializer<MyOuterClass> {
      @Override
      public MyOuterClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {


         MyOuterClass ans = new MyOuterClass();

         JsonToken token;

         token = p.getCurrentToken();
         if( token != JsonToken.START_OBJECT ) {
            throw new JsonParseException("Start object expected", p.getCurrentLocation());
         }

         if( !"inner".equals(p.nextFieldName() ) ) {
            throw new JsonParseException("'inner; field expected", p.getCurrentLocation());
         }

         MyInnerClass inner = null;// how to desrialize inner from here with default processing???
         ans.setInner(inner);

         token = p.nextToken();
         if( token != JsonToken.END_OBJECT ) {
            throw new JsonParseException("End object expected", p.getCurrentLocation());
         }

         return ans;

      }
   }

   public static class MyInnerClass {
      private int value;

      public int getValue() {
         return value;
      }

      public void setValue(int value) {
         this.value = value;
      }

      @Override
      public String toString() {
         return "{\"value\":" + value + "}";
      }
   }

   @JsonDeserialize(using = MyOuterClassDeserializer.class)
   @JsonSerialize(using = MyOuterClassSerializer.class)
   public static class MyOuterClass {

      private MyInnerClass inner;

      public MyInnerClass getInner() {
         return inner;
      }

      public void setInner(MyInnerClass inner) {
         this.inner = inner;
      }

      @Override
      public String toString() {
         return "{\"inner\":" + Objects.toString(inner) + "}";
      }
   }

   public static void main(String[] args) throws IOException {

      ObjectMapper mapper = new ObjectMapper();
      String string;

      MyInnerClass inner = new MyInnerClass();
      inner.setValue(12);

      MyOuterClass outer = new MyOuterClass();
      outer.setInner(inner);

      string = mapper.writeValueAsString(outer);
      System.out.println(string);

      MyOuterClass outer2 = mapper.readValue(string, MyOuterClass.class);
      System.out.println(outer2); // inner was not deserialized


   }
}

如何实施MyOuterDeserializer

1 个答案:

答案 0 :(得分:6)

DeserializationContext提供了这些工具。

检查"inner"的字段名称后,移动到下一个标记,即JSON对象的开头,并使用DeserializationContext将JSON对象反序列化为MyInnerClass对象。 / p>

if (!"inner".equals(p.nextFieldName())) {
    throw new JsonParseException("'inner; field expected", p.getCurrentLocation());
}
p.nextToken(); // consumes the field name token

MyInnerClass inner = ctxt.readValue(p, MyInnerClass.class);

javadoc陈述

  

复合材料或容器可以使用的便捷方法   反序列化器,用于读取包含的一次性值(对于序列,它   实际上为整体提取一次反序列化器效率更高   集合)。

使用DeserializationContext时要小心。不要尝试递归反序列化已注册自定义反序列化器的类型。