gpt4 book ai didi

java - SnakeYAML正在实例化ArrayList而不是HashMap

转载 作者:行者123 更新时间:2023-11-30 05:36:55 25 4
gpt4 key购买 nike

我需要解析以下 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));
}
}

解析器似乎运行良好,但在 Debug模式下运行此代码时,某些字段已使用正确的类型(HashSet)实例化,而其他字段则没有。它们被实例化为 ArrayLists(我不知道这里发生了什么样的魔法)。

这是调试窗口的快照:

Bug snapshot[1]

我的测试类的输出:

{
"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>

有人遇到过这个问题吗?我找不到解决方案。

最佳答案

您的问题可能是type erasure :

When type-safe (generic) collections are JavaBean properties SnakeYAML dynamically detects the required class. […]

It does not work if generic type is abstract class (interface). You have to put an explicit tag in the YAML or provide the explicit TypeDescription. TypeDescription serves the goal to collect more information and use it while loading/dumping.

虽然您不使用抽象类或接口(interface),但我假设 SnakeYaml 在发现 HashSet<HashMap<String, HashSet>> 的嵌套泛型类型时存在问题。 。文档建议添加 TypeDescription;但这并不能解决您的问题,因为接口(interface)的设计使您只能指定外部 HashSet 内部的类型,但不在内部HashMap内。该接口(interface)不需要嵌套容器的事实也暗示这是您的问题。

解决方法是在 YAML 中将显式标记添加到无法正确加载的集合中:

- Database: !!set ["D1"]
- MetaFeature: !!set ["M1", "M2"]

如果您不想这样做,您基本上还有另外两个选择:将此功能修补到 SnakeYAML 中,或者使用低级 API 并从解析器事件手动生成类型。

关于java - SnakeYAML正在实例化ArrayList而不是HashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56411334/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com