我需要解析以下YAML文件。
arguments:
- Database
- Fold
- MetaFeature
- Algorithm
- Config
processes:
- id: MetaFeatureCalculator
command: "python metaFeatCalc.py {Database} folds/{Fold} de/{MetaFeature}/{Algorithm}.csv"
in: [Database, Fold]
out: [MetaFeature, Algorithm]
log: "mf/{Fold}/{MetaFeature}.out"
- id: Tunner
command: "java -jar tunner.jar {MetaFeature} alg/{Algorithm} {config}"
in: [Metafeature, Algorithm]
out: [Config]
log: "mf/{Metafeature}/{Algorithm}.out"
recipeDefaults:
- Database: ["D1"]
recipes:
- id: Ex1
uses:
- Database: ["D1", "D2"]
- MetaFeature: ["M1", "M2"]
- Algorithm: ["A1", "A2"]
- Config: ["C1", "C4"]
- id: Ex2
uses:
- Folds: ["F1", "F2", "F5"]
- MetaFeature: ["M1", "M2"]
- Algorithm: ["A1", "A2"]
- Config: ["C1", "C4"]
然后我创建了以下POJO来接收此数据。
回购:https://github.com/Pacheco95/ExperimentLoader
@Data
public class Experiment {
private HashSet<String> arguments;
private HashSet<Process> processes;
private HashSet<HashMap<String, HashSet<String>>> recipeDefaults;
private HashSet<Recipe> recipes;
}
@Data
public class Process {
private String id;
private String command;
private HashSet<String> in;
private HashSet<String> out;
private String log;
}
@Data
public class Recipe {
private String id;
private HashSet<HashMap<String, HashSet>> uses;
}
该类用于测试解析器:
public class ExperimentLoader {
public static void main(String[] args) throws IOException {
InputStream is = args.length == 0 ? System.in : Files.newInputStream(Paths.get(args[0]));
Yaml yaml = new Yaml();
Experiment experiment = yaml.loadAs(is, Experiment.class);
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
System.out.println(gson.toJson(experiment));
}
}
解析器似乎运行良好,但是在调试模式下运行此代码时,某些字段已使用正确的类型(HashSet)实例化,而其他字段则没有。它们被实例化为ArrayLists(我不知道这里发生了什么魔术)。
这是脱胶窗口的快照:
我的测试课的输出:
{
"arguments": [
"Fold",
"MetaFeature",
"Config",
"Database",
"Algorithm"
],
"processes": [
{
"id": "MetaFeatureCalculator",
"command": "python metaFeatCalc.py {Database} folds/{Fold} de/{MetaFeature}/{Algorithm}.csv",
"in": [
"Fold",
"Database"
],
"out": [
"MetaFeature",
"Algorithm"
],
"log": "mf/{Fold}/{MetaFeature}.out"
},
{
"id": "Tunner",
"command": "java -jar tunner.jar {MetaFeature} alg/{Algorithm} {config}",
"in": [
"Metafeature",
"Algorithm"
],
"out": [
"Config"
],
"log": "mf/{Metafeature}/{Algorithm}.out"
}
],
"recipeDefaults": [
{
"Database": [
"D1"
]
}
],
"recipes": [
{
"id": "Ex2",
"uses": [
{
"MetaFeature": [
"M1",
"M2"
]
},
{
"Folds": [
"F1",
"F2",
"F5"
]
},
{
"Config": [
"C1",
"C4"
]
},
{
"Algorithm": [
"A1",
"A2"
]
}
]
},
{
"id": "Ex1",
"uses": [
{
"MetaFeature": [
"M1",
"M2"
]
},
{
"Config": [
"C1",
"C4"
]
},
{
"Database": [
"D1",
"D2"
]
},
{
"Algorithm": [
"A1",
"A2"
]
}
]
}
]
}
我的依赖项:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.24</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
有人遇到过这个问题吗?我找不到解决方法。
答案 0 :(得分:1)
您的问题可能是type erasure:
当类型安全(通用)集合是JavaBean属性时,SnakeYAML动态检测所需的类。 […]
如果泛型类型是抽象类(接口),则该方法不起作用。您必须在YAML中放置一个显式标签或提供显式TypeDescription。 TypeDescription的目标是收集更多信息并在加载/转储时使用它。
虽然您不使用抽象类或接口,但我认为SnakeYaml在发现HashSet<HashMap<String, HashSet>>
的嵌套泛型类型方面存在问题。该文档建议添加TypeDescription。但是,这不能解决您的问题,因为设计了接口,因此您只能在外部HashSet
内部指定类型,而不能在内部HashMap
内部指定类型。接口不希望嵌套容器,这一事实也暗示这是您的问题。
一种解决方法是将YAML内部的显式标记添加到无法正确加载的集合:
- Database: !!set ["D1"]
- MetaFeature: !!set ["M1", "M2"]
如果您不想这样做,则基本上还有两个选择:将此功能修补到SnakeYAML中,或使用低级API并从解析器事件中手动生成类型。