首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Jackson-Databind序列化java.time类的类型信息?

如何使用Jackson-Databind序列化java.time类的类型信息?
EN

Stack Overflow用户
提问于 2019-08-02 22:07:15
回答 2查看 209关注 0票数 1

我目前正在致力于将一个遗留应用程序从java.util.Date类移植到java.time应用程序接口。我使用默认类型来保存类型信息。因为java.time类被标记为final,所以Jackson没有在JSON输出中添加任何类型信息。这在大多数情况下都是可以的,但在这种情况下除外:

我有一个类,它有一个Object类型的成员,它可以包含各种数据类型。它是在运行时填充的,所以我不知道它会提前包含哪种数据类型。然后将其序列化并发送到客户端,客户端对其进行反序列化并使用instanceof检查数据类型。这在java.util.Date中工作得很好,因为类型是序列化的。由于没有类型信息,ZonedDateTime被反序列化为一个字符串,这会在后面的代码中导致错误。

我已经阅读了关于不同DefaultTyping-Settings的杰克逊文档,但添加了最多类型信息的选项似乎是NON_FINAL,这仍然会导致这个问题。

我还试图编写自己的序列化程序并覆盖serializeWithType-Method,但它从未被调用过。

我可以编写一个包含ZonedDateTime的非最终包装类,但如果可能的话,我想避免这种情况。

这是我的ObjectMapper配置:

代码语言:javascript
复制
ObjectMapper myMapper = new ObjectMapper()
                    .enable(MapperFeature.AUTO_DETECT_CREATORS)
                    .enable(MapperFeature.AUTO_DETECT_FIELDS)
                    .enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)
                    .disable(MapperFeature.AUTO_DETECT_GETTERS)
                    .disable(MapperFeature.AUTO_DETECT_SETTERS)
                    .disable(MapperFeature.USE_ANNOTATIONS)
                    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                    .enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)
                    .setSerializationInclusion(JsonInclude.Include.NON_NULL)
                    .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
                    .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
                    .registerModule(new JavaTimeModule());

这是我现在得到的结果:

代码语言:javascript
复制
"2019-08-02T16:03:41.988+02:00[Europe/Berlin]"

这就是我想要的:

代码语言:javascript
复制
["java.time.ZonedDateTime", "2019-08-02T16:03:41.988+02:00[Europe/Berlin]"]
EN

回答 2

Stack Overflow用户

发布于 2019-08-08 18:00:20

由于另一个答案在我的情况下不适用,我已经实现了一个变通方法。它不是很优雅,如果有人有更好的解决方案,我会删除它,但目前它是有效的。

我是通过使用泛型实现以下包装类来实现的:

代码语言:javascript
复制
 public class FinalClassContainer <T> {
    private T containedObject;

    public FinalClassContainer(T obj)
    {
        this.containedObject = obj;
    }

    public T getContainedClass()
    {
        return containedObject;
    }
}

这将产生以下输出:

代码语言:javascript
复制
[
    "com.test.FinalClassContainer",
    {
        "containedObject": [
            "java.time.ZonedDateTime",
            "2019-08-08T11:22:00.996+02:00[Europe/Berlin]"
        ]
    }
]

这允许我在客户端调用container.getContainedClass(),它返回具有正确类型的对象。

票数 1
EN

Stack Overflow用户

发布于 2019-08-06 16:14:12

这可以通过为Jackson提供一个生成所需输出的getter方法来实现。如果你有一个实例变量的getter方法,你可以告诉Jackson忽略它:

代码语言:javascript
复制
public class MyBean
{
    private Object obj;

    // tell jackson to ignore standard getter method
    @JsonIgnore
    public Object getObj() {
        return obj;
    }

    // this is the method that jackson will call during serialization
    @JsonProperty("obj")
    public String[] getObjForJson() {
        return new String[] {
            obj.getClass().getName(),
            obj.toString()
        };
    }
}

测试方法

代码语言:javascript
复制
public static void main(String[] args) {
    MyBean myBean = new MyBean();
    myBean.obj = ZonedDateTime.now();
    ObjectMapper mapper = new ObjectMapper();
    try {
        mapper.writeValue(System.out, myBean);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出:

代码语言:javascript
复制
{"obj":["java.time.ZonedDateTime","2019-08-06T11:09:30.467+03:00[Asia/Jerusalem]"]}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57328109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档