Java 从表示不同类的多个YAML文档中解析单个POJO

Java 从表示不同类的多个YAML文档中解析单个POJO,java,yaml,deserialization,snakeyaml,Java,Yaml,Deserialization,Snakeyaml,我想使用一个YAML文件,其中包含多个不同的对象-用于不同的应用程序。我需要获取一个对象来获取MyClass1的实例,忽略MyClass2、MyClass3等的其余文档。某种选择性的反序列化:现在是这个类,然后是那个类。。。使用MyClass1的应用程序完全不知道MyClass2、MyClass3的结构。当然,该文件始终是有效的YAML YAML可以是实现这种多类容器所需的任何结构。首选的解析工具是snakeyaml 这明智吗?除了一个对象,我怎么能忽略所有对象 UPD:将所有“文档”替换为“对

我想使用一个YAML文件,其中包含多个不同的对象-用于不同的应用程序。我需要获取一个对象来获取MyClass1的实例,忽略MyClass2、MyClass3等的其余文档。某种选择性的反序列化:现在是这个类,然后是那个类。。。使用MyClass1的应用程序完全不知道MyClass2、MyClass3的结构。当然,该文件始终是有效的YAML

YAML可以是实现这种多类容器所需的任何结构。首选的解析工具是snakeyaml

这明智吗?除了一个对象,我怎么能忽略所有对象

UPD:将所有“文档”替换为“对象”。我认为我们必须讨论一个YAML文档,它包含多个结构不同的对象。更重要的是,解析器只知道一个结构,并且希望忽略其余的结构

UDP2:我认为用snakeyaml是不可能的。无论如何,我们必须读取所有对象,然后选择所需的对象。但也许我错了

UPD2:示例配置文件

--- 
- 
  exportConfiguration781: 
    attachmentFieldName: "name"
    baseSftpInboxPath: /home/user/somedir/
    somebool: false
    days: 9999
    expected: 
      - ABC w/o quotes
      - "Cat ABC"
      - "Some string"
    dateFormat: yyyy-MMdd-HHmm
    user: someuser
- 
  anotherConfiguration: 
    k1: v1
    k2: 
      - v21
      - v22

这在SnakeYAML中是绝对可能的,尽管不是微不足道的。以下是您需要做的一般概述:

首先,让我们看看SnakeYAML的加载功能。以下是
YAML
类的重要部分:

私有对象loadFromReader(StreamReader sreader,类类型){
Composer-Composer=new-Composer(new-ParserImpl(sreader)、解析器、加载配置);
构造函数.setComposer(编写器);
返回构造函数.getSingleData(类型);
}
编写器将YAML输入解析为节点。要做到这一点,它不需要任何关于类结构的知识,因为每个节点都是ScalarNode、SequenceNode或MappingNode,它们只表示YAML结构

构造函数获取由编写器生成的根节点,并从中生成本机POJO。因此,您要做的是在节点图的部分到达构造函数之前丢弃它们

最简单的方法可能是从
Composer
派生并重写以下两种方法:

公共类MyComposer扩展了Composer{
私人最终内部索引;
公共MyComposer(解析器、解析器、解析器、int-objIndex){
超级(解析器、解析器);
this.objIndex=objIndex;
}
公共MyComposer(解析器、解析器、LoaderOptions loadingConfig、int-objIndex){
超级(解析器、解析器、加载配置);
this.objIndex=objIndex;
}
@凌驾
公共节点getNode(){
返回条(super.getNode());
}
专用节点条(节点输入){
return((SequenceNode)input.getValue().get(objIndex);
}
}
strip
实现只是一个例子。在本例中,我假设您的YAML如下所示(对象内容是任意的):

-{first:obj}
-{second:obj}
-{third:obj}
您只需通过序列中的索引选择实际要反序列化的对象。但是你也可以有更复杂的东西,比如搜索算法

既然你有了自己的作曲家,你就可以

Constructor=新构造函数();
//假设我们想要得到索引1处的对象(即第二个对象)
Composer Composer=new MyComposer(new ParserImpl(sreader),new Resolver(),1);
构造函数.setComposer(编写器);
MyObject结果=(MyObject)构造函数.getSingleData(MyObject.class);

对@flyx的回答对我很有帮助,通过覆盖一些方法,打开了解决库(在我们的例子中是snakeyaml)限制的方法。谢谢!它很可能有一个最终的解决方案,但不是现在。此外,下面的简单解决方案是健壮的,即使我们已经找到了完整的库入侵解决方案,也应该予以考虑

我决定通过双重提取来解决这个任务,对不起,处理配置文件。假设后者由几个部分组成,每个部分都由唯一的标记分隔符标记。为了保存YAML的肖像,它可能是

---
#this is a unique key for the configuration A
<some YAML document>
---
#this is another key for the configuration B
<some YAML document
现在,我们将文件字符串提供给简单的YAML解析

ExportConfiguration configuration = new Yaml(new Constructor(ExportConfiguration.class))
    .loadAs(fileString, ExportConfiguration.class);
这一次,我们只有一个文档必须共同响应ExportConfiguration类

注1:配置文件其余部分的结构甚至内容都完全不起作用。这是主要的想法,在一个文件中获得独立的配置


注2:其余配置可能是JSON或XML或其他任何形式。我们有一个返回字符串配置的方法预处理器,下一个处理器将正确解析它。

谢谢您的回答!实现的问题是strip()不起作用。异常表示ScalarNode不能强制转换为SequenceNode,这是合理的。而且,是的,我的YAML看起来和你想象的一模一样。而且,我一次也不想脱衣服。如果下面的obj中有一些节点树(实际上有),会怎么样?如果strip()处于活动状态,将如何解析它?您真的应该在问题中添加一些示例YAML,以显示您需要如何剥离它。我更新了代码。结果是
getSingleNode()
调用
getNode()
,因此覆盖第一个会导致调用
strip()
两次。恐怕我没有真正的Java调试设置,所以请检查它是否适用于这个简单的情况。我已经添加了示例配置文件。查看您的更改,我仍然不了解条带中的铸造()。这肯定会导致例外。
ExportConfiguration configuration = new Yaml(new Constructor(ExportConfiguration.class))
    .loadAs(fileString, ExportConfiguration.class);