包含对象列表的 SnakeYaml 反序列化类

Posted

技术标签:

【中文标题】包含对象列表的 SnakeYaml 反序列化类【英文标题】:SnakeYaml Deserialise Class containing a List of Objects 【发布时间】:2017-07-21 13:39:32 【问题描述】:

我正在尝试使用snakeyaml 将下面的YAML 反序列化到下面的域模型中,但是我不断收到java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to ConfigurableThing。

请注意,我能够成功反序列化单个 ConfigurableThing,只有在尝试反序列化我遇到问题的 ConfigurableThing 列表时。

要反序列化的代码

File file = new File(classLoader.getResource("config.yml").getFile());

        try(InputStream in = new FileInputStream(file))
            Yaml yaml = new Yaml();
            Configuration config = yaml.loadAs(in,Configuration.class);
        

YAML

things:
 - type: TYPE1
   name: foo
   value: 2.00
 - type: TYPE2
   name: bar
   value 8.00

型号

public final class Config 

    private List<ConfigurableThing> things;

    //Getter and Setter



public final class ConfigurableThing 

    private Type type;

    private String name;

    private BigDecimal value;

    //Getters and Setters


public enum Type 
    TYPE1,TYPE2

【问题讨论】:

【参考方案1】:

您没有显示用于加载 YAML 的代码,但您的问题可能是您没有正确注册集合类型。试试这个:

Constructor constructor = new Constructor(Config.class);
TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putListPropertyType("things", ConfigurableThing.class);
constructor.addTypeDescription(configDesc);
Yaml yaml = new Yaml(constructor);
Config config = (Config) yaml.load(/* ... */);

您需要这样做的原因是类型擦除——SnakeYaml 无法在运行时确定List 接口的泛型参数。所以你需要告诉它构造列表项为ConfigurableThing;如果你不这样做,将构造一个HashMap。这就是您在错误消息中看到的内容。

【讨论】:

完美,谢谢!为了后代,我添加了我使用加载 YAML 的错误代码。 您的编辑建议是正确的,尽管人们拒绝了它。 addTypeDescription 是正确的名称; SnakeYaml 文档使用 addTypeDefinition 这是错误的。 它可以工作,但只是添加了几行,这说明了最后一行发生的更多情况:File file = new File("configuration.yaml"); InputStream in = new FileInputStream(file);配置列表 = (Config)yaml.load(in); @SilverBlaze 由于 OP 添加了加载 YAML 的代码,很明显它不是从文件中加载的,而是从资源中加载的,因此您的代码不适用于此问题。我故意省略了该代码,因为它与问题无关,即使我们假设有人想要加载文件,他们为什么要使用您的方法而不是 Files.newInputStream(Paths.get("configuration.yaml"))

以上是关于包含对象列表的 SnakeYaml 反序列化类的主要内容,如果未能解决你的问题,请参考以下文章

PHP原生类反序列化

使用 SnakeYaml 处理缺失的字段

2:如何反序迭代一个序列(字符串,列表,元组)

Jackson - 使用泛型类反序列化

Boost 将派生类反序列化为基类指针

C#中通过XmlSerializer类反序列化多个同名XML元素