Reputation: 8560
Given the following yml:
---
commands:
dev: !foo.bar.Baz {}
And the following class
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;
}
And reading the file:
mapper.readValue(theFile, PluginFile.class);
Results in error:
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"])
Which seems to be saying that Jackson cannot determine the concrete instance of the Command to set on pluginFile.commands(). However, that type is defined and created by the yml file itself with the !foo.bar.DevCommand {} syntax.
I can get this working by using the following yaml:
---
commands:
dev:
type: foo.bar.Baz
And then annotating the map property:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="type")
But I really want to use the yaml Java literal syntax.
Upvotes: 0
Views: 711
Reputation: 116582
Base class Command
would need to have @JsonTypeInfo
to indicate it requires polymorphic handling; and if so, Jackson would know to look for Type Identifier that YAML content has. If foo.bar.Baz
specifies a class (that is, package foo.bar
, class Baz
), type inclusion should be specified as "class name".
Or, alternatively, you can specify @JsonTypeInfo
for the map property as well. Something like:
public class PluginFile {
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)
private Map<String, Command> commands = new HashMap<String, Command>();
}
Upvotes: 1