向 Jackson 反序列化器添加自定义参数

Adding custom arguments to Jackson deserializer

我有一个自定义解串器。但我希望能够传递额外的参数。例如

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

如何在注释中传递我的自定义参数?

您不能将自己的参数添加到 @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 ...;
    }
}

根据之前的解决方案,我创建了我的自定义日期deserializer.And它对我有用。

首先创建您的注释。

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

其次创建序列化程序class。

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