Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Jackson数据绑定序列化java.time类的类型信息?_Java_Json_Jackson_Java Time_Jackson Databind - Fatal编程技术网

如何使用Jackson数据绑定序列化java.time类的类型信息?

如何使用Jackson数据绑定序列化java.time类的类型信息?,java,json,jackson,java-time,jackson-databind,Java,Json,Jackson,Java Time,Jackson Databind,我目前正在将一个遗留应用程序从java.util.Date类移植到java.time API。我使用默认类型来保留类型信息。 由于java.time类被标记为final,Jackson不会在JSON输出中添加任何类型信息。这基本上是可以的,但在这种情况下: 我有一个类,它有一个类型对象的成员,可以包含各种数据类型。它是在运行时填充的,所以我不知道它将提前包含哪种数据类型。然后将其序列化并发送到客户端,客户端将其反序列化并使用instanceof检查数据类型。 这在java.util.Date中运

我目前正在将一个遗留应用程序从java.util.Date类移植到java.time API。我使用默认类型来保留类型信息。 由于java.time类被标记为final,Jackson不会在JSON输出中添加任何类型信息。这基本上是可以的,但在这种情况下:

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

我已经阅读了关于不同的
DefaultTyping
-设置的Jackson文档,但是添加最多类型信息的选项似乎是
NON_FINAL
,这仍然会导致此问题

我还尝试编写自己的序列化程序并覆盖
serializeWithType
-方法,但它从未被调用

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

以下是我的ObjectMapper配置:

ObjectMapper myMapper=new ObjectMapper()
.enable(MapperFeature.AUTO\u DETECT\u创建者)
.enable(MapperFeature.AUTO\u DETECT\u字段)
.enable(序列化功能。使用区域ID写入日期)
.disable(MapperFeature.AUTO\u DETECT\u getter)
.disable(MapperFeature.AUTO\u DETECT\u SETTERS)
.disable(MapperFeature.USE_注释)
.disable(序列化功能。将日期写入时间戳)
.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.setVisibility(PropertyAccessor.ALL、JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.FIELD,JsonAutoDetect.Visibility.ANY)
.registerModule(新的JavaTimeModule());
这就是我现在得到的结果:

"2019-08-02T16:03:41.988+02:00[Europe/Berlin]"
这就是我想要的:

["java.time.ZonedDateTime", "2019-08-02T16:03:41.988+02:00[Europe/Berlin]"]

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

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()
        };
    }
}
试验方法

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();
    }
}
输出:

{"obj":["java.time.ZonedDateTime","2019-08-06T11:09:30.467+03:00[Asia/Jerusalem]"]}

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

我使用泛型类型实现了以下包装器类:

 public class FinalClassContainer <T> {
    private T containedObject;

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

    public T getContainedClass()
    {
        return containedObject;
    }
}

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

这不是我的主字段,所以只需询问:您在使用吗?如果你这样做会有帮助吗?我已经包括并注册了
jackson-datatype-jsr310
。我现在也尝试了包含
jackson-datatype-jdk8
,但没有任何区别。遗憾的是,这在我的情况下不起作用,因为可以保存在成员变量中的其他对象可能需要进一步序列化。这个答案为问题提供了一个解决方案。也许您需要澄清问题中的完整要求。
[
    "com.test.FinalClassContainer",
    {
        "containedObject": [
            "java.time.ZonedDateTime",
            "2019-08-08T11:22:00.996+02:00[Europe/Berlin]"
        ]
    }
]