【问题标题】:Adding custom arguments to Jackson deserializer向 Jackson 反序列化器添加自定义参数
【发布时间】:2021-08-12 07:18:35
【问题描述】:

我有一个自定义反序列化器。但我希望能够传递额外的参数。例如

@JsonDeserialize(using=CustomDeserializer.class, customParm=value)
MyObject obj;

如何在注解上传入我的自定义参数?

【问题讨论】:

    标签: java json jackson deserialization


    【解决方案1】:

    根据以前的解决方案,我创建了我的自定义日期反序列化器。它对我有用。

    首先创建您的注释。

    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CustomDateFormat {
        String customDateFormat();
    }
    

    第二次创建您的序列化程序类。

    public class CustomDateDeserializer extends StdDeserializer<DateTime> implements ContextualDeserializer {
    
    private SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
    private String customDateFormat = null;
    
    public CustomDateDeserializer() {
        this(null);
    }
    
    public CustomDateDeserializer(Class<?> vc) {
        super(vc);
    }
    public CustomDateDeserializer(Class<?> vc, String customDateFormat) {
        super(vc);
        this.customDateFormat = customDateFormat;
    }
    
    @Override
    public DateTime deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
        String date = jsonparser.getText();
        try {
    
            if (!Util.nullToBosluk(date).equals(""))
                return new DateTime(getDateFormat(this.customDateFormat).parse(date));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return null;
     }
    
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
            throws JsonMappingException {
        CustomDateFormat customDateFormatAnn = property.getAnnotation(CustomDateFormat.class);
        if (customDateFormatAnn != null) {
            String customParam = customDateFormatAnn.customDateFormat();
            return new CustomDateDeserializer(this._valueClass, customParam);
        }
        return this;
     }
    
    private DateFormat getDateFormat(String customDateFormat) {
        if (StringUtils.isNotBlank(customDateFormat))
            return new SimpleDateFormat(customDateFormat);
        else
            return this.formatter;
     }
    }
    

    最后在你的代码中使用你的新注解。

    ...
    @JsonDeserialize(using = CustomDateDeserializer.class)
    DateTime invoiceDate;
    @JsonDeserialize(using = CustomDateDeserializer.class)
    @CustomDateFormat(customDateFormat = "dd/MM/yyyy HH:mm")
    DateTime createDate;
    ...
    

    【讨论】:

      【解决方案2】:

      您不能将自己的参数添加到@JsonDeserialize, 因为你不能改变 Jackson 对这个注解的实现。

      但是,您可以通过稍微不同的方式实现您的目标。 你可以发明自己的注解(我们称之为@MyAnnotation) 并将其与您的属性上的 @JsonDeserialize 注释一起使用:

      @JsonDeserialize(using = CustomDeserializer.class)
      @MyAnnotation(customParm = "value")
      private MyObject obj;
      

      注解的实现非常简单。 以下示例注释只定义了一个 String 参数。

      @Target({ ElementType.FIELD })
      @Retention(RetentionPolicy.RUNTIME)
      public @interface MyAnnotation {
      
          String customParm();
      }
      

      然后就可以从内部访问@MyAnnotation的参数了 你的反序列化器如下。

      • 像往常一样,您的反序列化器需要实现deserialize 方法 您在其中进行属性的实际反序列化。

      • 除了你的反序列化器需要实现 ContextualDeserializer interface 并实施createContextual method。 在这里你配置你的解串器(通过从@MyAnnotation 获取customParm)。 Jackson 会在实际反序列化之前调用此方法。

      public class CustomDeserializer extends StdDeserializer<MyObject> implements ContextualDeserializer {
      
          private String customParm = null;
      
          public CustomDeserializer() {
              super(MyObject.class);
          }
      
          public CustomDeserializer(String customParm) {
              super(MyObject.class);
              this.customParm = customParm;
          }
      
          @Override
          public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
                  throws JsonMappingException {
              MyAnnotation myAnnotation = property.getAnnotation(MyAnnotation.class);
              if (myAnnotation != null) {
                  String customParm = myAnnotation.customParm();
                  // return a new instance, so that different properties will not share the same deserializer instance
                  return new CustomDeserializer(customParm);
              }
              return this;
          }
      
          @Override
          public MyObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
              // do your deserialization (using customParm)
              return ...;
          }
      }
      

      【讨论】:

      • 谢谢!我无法将构造函数的方式与我见过的其他示例相协调。它不太管用。我所看到的是以下内容: public DateDeserializer() { this(null); } public DateDeserializer(Class> vc) { super(vc);在我添加 createContextual() 之前,这对我来说很好。但是您正在传递反序列化器的类,它似乎导致它挂起。您确定超类构造函数的参数应该简单地硬编码为反序列化器的类吗?
      • 对不起,我说错了。我的意思是数据对象的类,而不是反序列化器
      • 搞定了。我的问题是,如果某些条件不满足,我会抛出 IOException 。这导致代码只是挂起,即使方法的签名有 IOException。抛出 RuntimeException 工作正常
      猜你喜欢
      • 1970-01-01
      • 2016-02-13
      • 2011-04-12
      • 2016-01-29
      • 1970-01-01
      • 2019-08-10
      • 2016-02-12
      • 2020-05-27
      • 1970-01-01
      相关资源
      最近更新 更多