在 Jackson 中以编程方式设置类型鉴别器
Set Type Discriminator programmatically in Jackson
对于多态反序列化,Jackson 的 ObjectMapper 想知道:
- 需要考虑哪些亚型
- 如何决定,使用哪个子类型
有一些标准方法,使用完全限定的 class 名称和某些保留的 JSON 属性,因此 Jackson 无需进一步配置就可以扣除这些东西。
另一种常见的方法是,通过向基本类型添加注释 @JsonTypeInfo
和 @JsonSubtypes
来为 Jackson 提供必要的信息。然而,这意味着,当添加新的子类型时,必须修改声明基础 class 的文件。
也可以在运行时通过 objectMapper.registerSubtypes(...)
.
以编程方式将子类型注册到 ObjectMapper
现在我正在寻找一种方法来在运行时以编程方式提供来自@JsonTypeInfo 的信息,而不使用该注释。
类似 objectMapper.addTypeInfo(new TypeInfo(BaseType.class, PROPERTY, "myPropertyName", NAME);
这样我就可以对在另一个项目中声明的类型使用多态反序列化,该项目对 Jackson 或其任何注释一无所知。
要在不修改实际 class 的情况下注册 @JsonTypeInfo
,您必须使用这样的混合:
// actual base type that we don't want to or can't modfiy
// because it is in a different module / 3rd party
public class BaseType {
...
}
// mixin for BaseType to define @JsonTypeInfo
// this can be in a completely different package / module
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
public abstract class BaseTypeMixIn {
}
必须为 ObjectMapper 手动注册 mixin:
objectMapper.addMixIn(BaseType.class, BaseTypeMixIn.class);
BaseType 现在有效地具有来自混入的 @JsonTypeInfo
。
jackson 中的 Mixin 是解决“How do I annotate a class that I can't modify”问题的一般解决方案。
对于子类型,可以使用 ObjectMapper.registerSubtypes
注册类型信息或通过使用 @JsonSubtypes
注释混合。在这种情况下,我更喜欢在没有注释的情况下进行操作,因为如果不同的模块具有基本类型的不同子类型,它也可以工作。注册多个 mixin 很可能不起作用。
public class SubTypeA extends BaseType {
...
}
public class SubTypeB extends BaseType {
...
}
在 ObjectMapper 中注册:
objectMapper.registerSubtypes(
new NamedType(SubTypeA.class, "A"),
new NamedType(SubTypeB.class, "B"));
对于多态反序列化,Jackson 的 ObjectMapper 想知道:
- 需要考虑哪些亚型
- 如何决定,使用哪个子类型
有一些标准方法,使用完全限定的 class 名称和某些保留的 JSON 属性,因此 Jackson 无需进一步配置就可以扣除这些东西。
另一种常见的方法是,通过向基本类型添加注释 @JsonTypeInfo
和 @JsonSubtypes
来为 Jackson 提供必要的信息。然而,这意味着,当添加新的子类型时,必须修改声明基础 class 的文件。
也可以在运行时通过 objectMapper.registerSubtypes(...)
.
现在我正在寻找一种方法来在运行时以编程方式提供来自@JsonTypeInfo 的信息,而不使用该注释。
类似 objectMapper.addTypeInfo(new TypeInfo(BaseType.class, PROPERTY, "myPropertyName", NAME);
这样我就可以对在另一个项目中声明的类型使用多态反序列化,该项目对 Jackson 或其任何注释一无所知。
要在不修改实际 class 的情况下注册 @JsonTypeInfo
,您必须使用这样的混合:
// actual base type that we don't want to or can't modfiy
// because it is in a different module / 3rd party
public class BaseType {
...
}
// mixin for BaseType to define @JsonTypeInfo
// this can be in a completely different package / module
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
public abstract class BaseTypeMixIn {
}
必须为 ObjectMapper 手动注册 mixin:
objectMapper.addMixIn(BaseType.class, BaseTypeMixIn.class);
BaseType 现在有效地具有来自混入的 @JsonTypeInfo
。
jackson 中的 Mixin 是解决“How do I annotate a class that I can't modify”问题的一般解决方案。
对于子类型,可以使用 ObjectMapper.registerSubtypes
注册类型信息或通过使用 @JsonSubtypes
注释混合。在这种情况下,我更喜欢在没有注释的情况下进行操作,因为如果不同的模块具有基本类型的不同子类型,它也可以工作。注册多个 mixin 很可能不起作用。
public class SubTypeA extends BaseType {
...
}
public class SubTypeB extends BaseType {
...
}
在 ObjectMapper 中注册:
objectMapper.registerSubtypes(
new NamedType(SubTypeA.class, "A"),
new NamedType(SubTypeB.class, "B"));