简体   繁体   中英

How to delegate to default deserialization in custom deserializer in Jackson?

Suppose I am writing custom serialization for some class, but would like to process one of its field with default methods.

How to do that?

While serializing we have JsonGenerator#writeObjectField() .

But what is corresponding method for deserialization?

Regard the code below:

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


   }
}

How to implement MyOuterDeserializer ?

The DeserializationContext offers these tools.

After checking the field name for "inner" , move to the next token, the beginning of the JSON object and use the DeserializationContext to deserialize the JSON object into a MyInnerClass object.

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);

The javadoc states

Convenience method that may be used by composite or container deserializers, for reading one-off values contained (for sequences, it is more efficient to actually fetch deserializer once for the whole collection).


Careful while using the DeserializationContext . Don't try to recursively deserialize types for which you have have registered custom deserializers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM