英文:
Set Type Discriminator programmatically in Jackson
问题
为了多态反序列化,Jackson的ObjectMapper需要知道以下信息:
- 有哪些子类型需要考虑
- 如何决定使用哪个子类型
有一些标准的方法,可以使用完全限定的类名和特定的保留JSON属性,这样Jackson可以在没有进一步配置的情况下推断出这些信息。
另一种常见的方式是通过将注解@JsonTypeInfo
和@JsonSubtypes
添加到基本类型来为Jackson提供必要的信息。然而,这意味着每当添加新的子类型时,声明基类的文件必须进行修改。
还可以在运行时通过objectMapper.registerSubtypes(...)
以编程方式向ObjectMapper注册子类型。
现在我正在寻找一种方法,在运行时以编程方式提供@JsonTypeInfo的信息,而不使用该注解。
类似于 objectMapper.addTypeInfo(new TypeInfo(BaseType.class, PROPERTY, "myPropertyName", NAME);
这样我可以在另一个项目中声明的类型上使用多态反序列化,该项目对Jackson或其任何注解一无所知。
英文:
For polymorphic deserialisation, Jackson's ObjectMapper wants to know:
- Which Subtypes are there to consider
- How to decide, which Subtype to use
There are some standard ways, using fully qualified class names and certain reserved JSON properties, so Jackson can deduct those things without further configuration.
Another common way is, to provice Jackson with the necessary infromation by adding the Annotations @JsonTypeInfo
and @JsonSubtypes
to the base type. This however implies, that the file, declaring the base class has to be modified, when ever a new subtype is added.
It is also possible to regiser subtypes to the ObjectMapper programmatically at runtime via objectMapper.registerSubtypes(...)
.
Now I am looking for a way to also provide the information from @JsonTypeInfo programmatically at runtime without using that annotation.
Somthing like objectMapper.addTypeInfo(new TypeInfo(BaseType.class, PROPERTY, "myPropertyName", NAME);
so I can use polymorphic deserialization on types that are declared in another project, that knows nothing of Jackson or any of its annotations.
答案1
得分: 5
要注册@JsonTypeInfo
而不修改实际类,您必须使用像这样的混合(mixin):
// 实际的基本类型,我们不想或不能修改它,因为它在不同的模块/第三方中
public class BaseType {
...
}
// BaseType的混合,用于定义@JsonTypeInfo
// 这可以在完全不同的包/模块中
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
public abstract class BaseTypeMixIn {
}
必须手动为ObjectMapper
注册混合:
objectMapper.addMixIn(BaseType.class, BaseTypeMixIn.class);
现在,BaseType从混合中有效地获得了@JsonTypeInfo
注解。Jackson中的混合是解决“如何为我无法修改的类添加注解”的一般解决方案。
对于子类型,可以使用ObjectMapper.registerSubtypes
注册类型信息,或者使用@JsonSubtypes
注解混合。在这种情况下,我更喜欢不使用注解来完成,因为这也适用于不同模块具有基本类型的不同子类型的情况。注册多个混合可能不太可能起作用。
public class SubTypeA extends BaseType {
...
}
public class SubTypeB extends BaseType {
...
}
在ObjectMapper中注册:
```java
objectMapper.registerSubtypes(
new NamedType(SubTypeA.class, "A"),
new NamedType(SubTypeB.class, "B"));
英文:
To register the @JsonTypeInfo
without modifying the actual class you have to use a mixin like this:
// 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 {
}
The mixin must be registered manually for the ObjectMapper:
objectMapper.addMixIn(BaseType.class, BaseTypeMixIn.class);
BaseType now effectively has the @JsonTypeInfo
from the mixin.
Mixin in jackson are the general solution to the problem "How do I annotate a class that I can't modify".
For sub-types the type info can be registered with ObjectMapper.registerSubtypes
or by annotating the mixin with @JsonSubtypes
. I prefer doing in without annotation in this case because it also works if different modules have different sub types of the base type. Registering multiple mixins will most likely not work.
public class SubTypeA extends BaseType {
...
}
public class SubTypeB extends BaseType {
...
}
Register in the ObjectMapper:
objectMapper.registerSubtypes(
new NamedType(SubTypeA.class, "A"),
new NamedType(SubTypeB.class, "B"));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论