Jackson:反序列化接口集的实例化子类(yml)

时间:2016-10-06 19:54:45

标签: java jackson yaml

给出以下yml:

---
  commands:
    dev: !foo.bar.Baz {}

以下课程

public class PluginFile {
    private Map<String, Command> commands = new HashMap<String, Command>();
    public Map<String, Command> getCommands() {
        return commands;
    }
    public void setCommands(Map<String, Command> commands) {
        this.commands = commands;
    }

阅读文件:

mapper.readValue(theFile, PluginFile.class);

导致错误:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of foo.bar.command.Command, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
 at [Source: C:\theFile.yml; line: 3, column: 10] (through reference chain: foo.bar.PluginFile["commands"]->java.util.LinkedHashMap["dev"])

这似乎是说杰克逊无法确定要在pluginFile.commands()上设置的Command的具体实例。但是,该类型是由yml文件本身使用!foo.bar.DevCommand {}语法定义和创建的。

我可以使用以下yaml来实现这一点:

---
  commands:
    dev: 
      type: foo.bar.Baz

然后注释地图属性:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="type")

但我真的想使用yaml Java文字语法。

1 个答案:

答案 0 :(得分:1)

基类Command需要@JsonTypeInfo来表明它需要多态处理;如果是这样,杰克逊会知道要查找YAML内容所具有的类型标识符。如果foo.bar.Baz指定了一个类(即包foo.bar,类Baz),则类型包含应指定为&#34;类名&#34;。

或者,您也可以为地图属性指定@JsonTypeInfo。类似的东西:

public class PluginFile {
  @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)
  private Map<String, Command> commands = new HashMap<String, Command>();
}