【问题标题】:Passing arguments to Java class used in @JsonSerialize and @JsonDeserialize将参数传递给 @JsonSerialize 和 @JsonDeserialize 中使用的 Java 类
【发布时间】:2021-03-13 03:46:07
【问题描述】:

我有一个我不知道如何用谷歌搜索的场景,所以我会自己提出一个问题。如果它是重复的,请在此处链接它,以便我可以给出这个问题。

不管怎样,

我有一个带有以下注释字段的 Java 对象:

@JsonSerialize(using = CustomSerializer.class)
@JSonDeserialize(using = CustomDeserializer.class)
private Date systemDate;

业务规定不同数据库中的某些 systemDate 值具有不同的时区(不确定为什么它们没有标准化为 UTC)。

这是我的CustomSerializer.java的一个例子:

@Override
public void serialize(Date, value, JsonGenerator gen, SerializerProvider arg2) throws IOException {
    SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
    formatter.setTimeZone(TimeZone.getTimeZone("CET"));
    if (value == null) {
        gen.writeNull();
    } else {
        gen.writeString(formatter.formate(value.getTime()));
    }
}

有没有办法将时区参数传递给这个类(以及我的Deserializer 类),而不是为每个时区创建一个新的序列化程序类?

【问题讨论】:

    标签: java serialization jackson


    【解决方案1】:

    您需要创建一个自定义注释,如下所示:

    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotation
    public @interface DateSerialize {
        String timeZone();
    }
    

    现在在 systemDate 字段中通过传递时区添加这个新注释

    @DateSerialize(timeZone = "UTC")
    @JsonSerialize(using = CustomSerializer.class)
    @JSonDeserialize(using = CustomDeserializer.class)
    private Date systemDate;
    

    您的序列化程序类应该实现ContextualSerializer,这将允许我们获取BeanProperty,我们可以从中获取注释详细信息。

    public class DateSerializer extends JsonSerializer<Date> implements ContextualSerializer {
        String timeZone;
    
        public DateSerializer() {
            this("UTC");
        }    
        
        public DateSerializer(String tz) {
            timeZone = tz;
        }
    
        @Override
        public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
            formatter.setTimeZone(TimeZone.getTimeZone(timeZone));
            if (value == null) {
                gen.writeNull();
            } else {
                gen.writeString(formatter.format(value.getTime()));
            }
        }
    
        @Override
        public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { 
            DateSerialize annotation = property.getAnnotation(DateSerialize.class);
            String tz = (annotation == null) ? "UTC" : annotation.timeZone();   
            return new DateSerializer(tz);
        }
    }
    

    同样,您可以通过实现ContextualDeserializer 创建一个反序列化器。

    【讨论】:

    • 我正在尝试实施您的解决方案,但我忘了提及我的 DateSerializer 扩展了 JsonSerializer。因此 super(t) 和 super(Date.class) 不起作用。
    • @AKJ 即使您扩展 JsonSerializer,它仍然可以工作(在删除这些构造函数之后)。我已经更新了答案。无论如何StdSerializer 扩展JsonSerializer
    • 它不工作,它仍然使用我的本地系统时间而不是 UTC。
    • @AKJ 您是否尝试调试createContextualserialize 中的代码以查看时间是否已格式化?
    猜你喜欢
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多