gpt4 book ai didi

java - 如何配置 Jackson 以使用默认类型反序列化命名类型?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:05:33 26 4
gpt4 key购买 nike

考虑以下示例:

package com.example;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;

public class JacksonDeserializationOfNamedTypes {
public static void main(String[] args) throws Exception {
ObjectMapper jackson = new ObjectMapper();
jackson.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, "@type");

Balloon redBalloon = new Balloon("red");

String json = jackson.writeValueAsString(redBalloon); //{"@type":"Balloon","color":"red"}
//assume the JSON could be anything
Object deserialized = jackson.readValue(json, Object.class);

assert deserialized instanceof Balloon;
assert redBalloon.equals(deserialized);
}

@JsonTypeName("Balloon")
@JsonTypeInfo(use = Id.NAME)
public static final class Balloon {
private final String color;

//for deserialization
private Balloon() {
this.color = null;
}

public Balloon(final String color) {
this.color = color;
}

public String getColor() {
return color;
}

@Override
public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final Balloon other = (Balloon) obj;
return this.color.equals(other.color);
}

@Override
public int hashCode() {
int result = color.hashCode();
result = 31 * result + color.hashCode();
return result;
}

@Override
public String toString() {
return color + " balloon";
}
}
}

反序列化在运行时失败,出现以下异常:线程“main”中的异常 java.lang.IllegalArgumentException:无效的类型 ID“气球”(对于 ID 类型“Id.class”):找不到这样的类

生成的 JSON 当然包含 Jackson 正确确定类型所需的所有信息,那么我如何配置 ObjectMapper 以将 "Balloon" 正确映射到 com.example.JacksonDeserializationOfNamedTypes$Balloon ?

最佳答案

The produced JSON certainly has all the information Jackson needs to determine the type correctly

您已向 Jackson 提供以下内容

Object deserialized = jackson.readValue(json, Object.class);

Object 是所有 Java 引用类型的父类(super class)型。这是众所周知的。对 jackson 不是很有用。您的 JSON 还包含

{"@type":"Balloon","color":"red"}

鉴于此并感谢

jackson.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, "@type");

Jackson 可以推断它可以使用 @type 元素的值。但是,它可以用名称 Balloon 做什么? Jackson 不知道类路径上的所有类型。您是否有完全限定名称 Balloon 的类型?您是否有一个名为 com.example.Balloon 或名为 org.company.toys.Balloon 的类型? jackson 该如何选择?

@JsonTypeInfo 和注释系列通常用于继承层次结构的反序列化。例如

@JsonTypeInfo(use = Id.NAME)
@JsonSubTypes(value = @Type(value = Balloon.class))
public abstract static class Toy {

}

@JsonTypeName("Balloon")
public static final class Balloon extends Toy {

Object deserialized = jackson.readValue(json, Toy.class);

现在 Jackson 可以查找 Toy 类及其元数据,这些元数据将其子类标识为 Balloon,它还可以检查名称 Balloon.

如果您不尝试对继承层次结构建模,这里最简单的解决方案是在@JsonTypeName注解。

@JsonTypeName("com.example.JacksonDeserializationOfNamedTypes$Balloon")
@JsonTypeInfo(use = Id.NAME)
public static final class Balloon {

然后该名称将出现在 JSON 中,Jackson 将使用它来确定目标类。

关于java - 如何配置 Jackson 以使用默认类型反序列化命名类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38380412/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com