使用 Jackson 对多态类反序列化 JSON



我正在尝试反序列化可以是GroupRule或AttributeRule的JSON:

AbstractRule
GroupRule
AttributeRule

我希望我的模型/实体/POJO 是通用的,因为我也在具有 Snakeyaml 或其他序列化提供程序的其他项目中使用相同的类。

话虽如此,我偶然发现了这个:https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization

在文章中,它表明我可以做到:

{ // Using fully-qualified path
"@class" : "com.fasterxml.beans.EmployeeImpl", ...
}

但是,当我这样做时,我得到:

Cannot construct instance of `com.walterjwhite.email.organization.api.configuration.rule.AbstractRule` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (FileInputStream); line: 4, column: 10] (through reference chain: com.walterjwhite.email.organization.api.configuration.rule.EmailMatcherRule["rule"])
com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)

我的配置是这样的:

{
"name": "default",
"ordering": "1",
"rule": {
"@class": "com.walterjwhite.email.organization.api.configuration.rule.GroupRule",
"criteriaType": "Should",
"rules": [
{"@class": "com.walterjwhite.email.organization.api.configuration.rule.AttributeRule",
"emailMessageField": "Subject",
"values": ["default"]
}
]
},
"matchType": "ContainsIgnoreCase",
"actionClassNames": [
"com.walterjwhite.email.organization.plugins.count.CountAction",
"com.walterjwhite.email.organization.plugins.index.IndexAction",
"com.walterjwhite.email.organization.plugins.reply.MoveAction"
]
}

在Java方面,我通常这样做:

mapper.readValue(inputStream, entityType);

现在,在这种情况下,实体类型是EmailMatcherRule,其中有一个规则字段,可以是属性或组。 输入流只是我正在传入的文件输入流...

我正在使用杰克逊 2.10.1。 我还从 YAML 转换了上述 JSON,它通过 Snakeyaml 工作正常。 请注意,它会自动将类嵌入到 YAML 中,因此这不是问题。

我的 JSON 是否正确 - 根据文档,我应该能够添加 @class 属性来指定我要使用的类,对吗?

我在下面尝试过,它无需任何配置即可工作。不确定这是否是您想要实现的目标:

public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String groupRuleStr = "{"parentId":"parent","groupId":"group"}";
String attributeRuleStr = "{"parentId":"parent","attributeId":"attribute"}";
GroupRule groupRule = mapper.readValue(groupRuleStr, GroupRule.class);
AttributeRule attributeRule = mapper.readValue(attributeRuleStr, AttributeRule.class);
System.out.println(groupRule.groupId);
System.out.println(attributeRule.attributeId);
}
static abstract class AbstractRule {
public String parentId = "parent";
}
static class GroupRule extends AbstractRule {
public String groupId = "group";
}
static class AttributeRule extends AbstractRule {
public String attributeId = "attribute";
}

我必须这样做:

objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator());

现在,我的 JSON 看起来像这样(注意:这是一个不同的测试实体,但你明白了(:

{
"name": "default",
"ordering": "1",
"rule": [
"com.walterjwhite.email.organization.api.configuration.rule.GroupRule",
{
"criteriaType": "Should",
"rules": ["java.util.HashSet",[[
"com.walterjwhite.email.organization.api.configuration.rule.AttributeRule",
{
"emailMessageField": ["com.walterjwhite.email.organization.api.configuration.rule.EmailMessageField", "Subject"],
"values": ["java.util.HashSet", [
"default"
]],
"matchType": ["com.walterjwhite.email.organization.api.configuration.rule.MatchType","ContainsIgnoreCase"]
}]]
]
}
],
"actionClassNames": ["java.util.ArrayList",[
"com.walterjwhite.email.organization.plugins.count.CountAction",
"com.walterjwhite.email.organization.plugins.index.IndexAction",
"com.walterjwhite.email.organization.plugins.reply.MoveAction"
]
]

}

因此,我看到的参考文档@class似乎不准确。 我对添加所有这些额外信息并不感到高兴,尤其是当其中一些不需要时 - java.util.ArrayList。

最新更新