java - 杰克逊中的多态反序列化为特定字段设置值 null
问题描述
问题陈述
是当我通过邮递员发送以下 JSON 时,要反序列化为以下给定 POJO 的 JSON 将 credentialType 的值设置为 null
{
"credential": [
{
"@type": "mobile",
"credentialName": "cred-2",
"email": "s@s.com"
},
{
"@type": "card",
"credentialNumber": "1"
}
]
}
预期结果
我想要实现的是,对于上述 JSON,凭证类型应设置为 MobileCredentialDto 的 MOBILE 或 CardCredentialDto 的 CARD
@Getter
公共类 SecureDto {
private List<CredentialDto> credential;
@JsonCreator
public HandoutDto(@JsonProperty("credential") final List<CredentialDto> credential) {
this.credential = Collections.unmodifiableList(credential);
}
}
@Getter
public class SecureDto {
private List<CredentialDto> credential;
@JsonCreator
public HandoutDto(@JsonProperty("credential") final List<CredentialDto> credential) {
this.credential = Collections.unmodifiableList(credential);
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = CardCredentialDto.class, name = "card"),
@JsonSubTypes.Type(value = MobileCredentialDto.class, name = "mobile"),
})
@Getter
@Setter
public class CredentialDto {
private CredentialType credentialType;
@JsonCreator
public CredentialDto(@JsonProperty("credentialType") final String credentialType) {
this.credentialType = CredentialType.valueOf(credentialType);
}
public CredentialDto() {
}
public void setCredentialType(final CredentialType credentialType) {
this.credentialType = CredentialType.MOBILE;
}
}
@Getter
@Setter
public class MobileCredentialDto extends CredentialDto {
private String credentialName;
private String email;
public MobileCredentialDto(final String credentialId,
final String state,
final String credentialNumber,
final String credentialName,
final String email) {
super(credentialId, state, credentialNumber, CredentialType.MOBILE.name());
this.credentialName = credentialName;
this.email = email;
}
public MobileCredentialDto() {
}
public String getCredentialName() {
return credentialName;
}
public String getEmail() {
return email;
}
}
@Getter
@Setter
public class CardCredentialDto extends CredentialDto {
public CardCredentialDto(final String credentialId,
final String state,
final String credentialNumber) {
super(credentialId, state, credentialNumber,CredentialType.CARD.name());
}
public CardCredentialDto() {
}
}
public enum CredentialType {
MOBILE("MOBILE"),
CARD("CARD");
private final String name;
CredentialType(final String name) {
this.name = name;
}
}
解决方案
我找到了答案。
我所做的是在 JsonTypeInfo 中设置了 visible = true。简而言之,通过设置 visible = true 允许杰克逊执行以下操作
关于类型标识符可见性的注意事项:默认情况下,类型标识符的反序列化(在读取 JSON 期间使用)完全由 Jackson 处理,并且不会传递给反序列化程序。但是,如果需要,可以定义属性 visible = true 在这种情况下,属性将在反序列化时按原样传递给反序列化器(并通过 setter 或字段设置)。
请参阅此处的文档以获得更多理解。 https://fasterxml.github.io/jackson-annotations/javadoc/2.4/com/fasterxml/jackson/annotation/JsonTypeInfo.html
下面是代码
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME ,
visible = true,
property = "credentialType")
@JsonSubTypes({
@JsonSubTypes.Type(value = CardCredentialDto.class, name = "card"),
@JsonSubTypes.Type(value = MobileCredentialDto.class, name = "mobile"),
})
@Getter
@Setter
public class CredentialDto {
@JsonProperty(value = "credentialType")
private CredentialType credentialType;
@JsonCreator
public CredentialDto(@JsonProperty("credentialType") final String credentialType) {
this.credentialType = CredentialType.valueOf(credentialType);
}
public CredentialDto() {
}
public void setCredentialType(final CredentialType credentialType) {
this.credentialType = CredentialType.MOBILE;
}
}
json看起来像这样
{
"credential": [
{
"credentialType": "mobile",
"credentialName": "cred-2",
"email": "s@s.com"
},
{
"credentialType": "card",
"credentialNumber": "1"
}
]
}
推荐阅读
- python - 使用多个字典编辑 .json
- python - 将两个列表转换为动态嵌套字典,然后转换为 JSON
- common-lisp - 如何返回对递归 lisp 函数中的列表所做的更改?
- node.js - 从模块返回流到快速路由
- swift - 离开增强现实视图后删除 _SCNSnapshotWindow
- php - URL 不显示错误/PHP
- python - 使用 python 的 bash 浮动数学
- r - 根据用户输入以闪亮的形式显示输出表并重置为默认表
- reactjs - 在反应静态 Firebase 托管应用程序中隐藏/屏蔽 API 密钥或敏感数据
- azure - Azure 应用服务是否支持扩展 ACL?