当前位置: 首页 > 知识库问答 >
问题:

如何在Jackson的自定义反序列化程序中委托到默认反序列化?

子车睿
2023-03-14

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

那要怎么做?

序列化时,我们有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个答案

尹赞
2023-03-14

DeseriazationContext提供了这些工具。

检查“inner”的字段名后,移动到下一个标记,即JSON对象的开头,并使用反序列化上下文将JSON对象反序列化为MyInnerClass对象

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声明

组合或容器反序列化程序可能使用的一种方便方法,用于读取包含的一次性值(对于序列,实际获取整个集合的反序列化程序一次更有效)。

使用反序列化上下文时要小心。不要尝试递归地反序列化已注册自定义反序列化程序的类型。

 类似资料:
  • 情况如下:我已经设法让Jackson反序列化以下通用 作为HTTP客户端,并使用exchange

  • 我在Jackson的自定义反序列化程序中有一个问题。我想访问默认序列化程序来填充我要反序列化到的对象。在填充之后,我将执行一些自定义操作,但首先我要使用默认的Jackson行为反序列化对象。 这是我现在有的代码。 我需要的是一种初始化默认反序列化器的方法,这样我就可以在开始我的特殊逻辑之前预填充我的POJO。 当从自定义反序列化程序内调用deserialize时,无论我如何构造序列化程序类,该方法

  • 我想通过扩展默认的反序列化器来创建自己的反序列化器,在其后面设置更多的值: 如您所见,我还想将此DTO母类重用于其他DTO。 我没有找到任何这样的例子。我真的是世界上第一个 反序列化的“AsUsual”(p,ctxt)应该是什么 我应该使用什么motherclass?JsonDeserializer/StdDeserializer/UntypedObjectDeserializer 反序列化程序会

  • 我想创建一个自定义序列化程序,它只做一点点工作,然后将其余部分留给默认序列化。 例如: 通过为聚合对象创建其他自定义序列化器的想法,这些对象根据“特殊”属性值表现不同。然而,上面的代码不起作用,因为它毫不奇怪地进入了无限递归。 一旦我设置了属性,有没有办法告诉jackson使用默认序列化?我真的不想像许多自定义序列化程序那样枚举所有属性,因为该类相当复杂,并且我不想每次更改该类时都必须对序列化程序

  • 我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif

  • I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器