在Jackson中以编程方式设置类型区分器(Type Discriminator)

huangapple go评论57阅读模式
英文:

Set Type Discriminator programmatically in Jackson

问题

为了多态反序列化,Jackson的ObjectMapper需要知道以下信息:

  1. 有哪些子类型需要考虑
  2. 如何决定使用哪个子类型

有一些标准的方法,可以使用完全限定的类名和特定的保留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:

  1. Which Subtypes are there to consider
  2. 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"));

huangapple
  • 本文由 发表于 2020年7月21日 20:35:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63014686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定