精确编辑yaml
Edit yaml in a precise way
我想在 java 中编辑一个 yaml,(我正在编辑 BungeeCord 配置文件以创建一个系统,该系统启动具有由用户端口定义的 bungeecord 实例)但以一种精确的方式,我需要在 yaml 文件中准确地写这个:
listeners:
- query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
我做了一些非常相似的事情,但是有一个竖线阻止 BungeeCord 读取文件:
public class ProxyYaml {
HashMap<String, Object> entries = new HashMap<String, Object>();
public ProxyYaml() {
entries.put("query_port", 25577);
entries.put("motd", "Hey Guys");
entries.put("tab_list", "GLOBAL_PING");
entries.put("query_enabled", false);
entries.put("proxy_protocol", false);
entries.put("ping_passthrough", false);
entries.put("priorities", Arrays.asList("lobby"));
entries.put("bind_local_address", true);
entries.put("host", "0.0.0.0:25577");
entries.put("max_players", 1);
entries.put("tab_size", 60);
entries.put("force_default_server", false);
}
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
}
(我正在使用 SimpleYaml api 但如果需要我可以更改 api )
File propsProxyFile = new File(path + "config.yml");
YamlFile propsProxyYaml = new YamlFile(propsProxyFile);
try {
propsProxyYaml.load(propsProxyFile);
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
propsProxyYaml.save(propsProxyFile);
} catch (IOException | InvalidConfigurationException e) {
System.out.println(MainNetwork.logo + "Can't load proxy properties file");
return;
}
有代码输出(带竖线):
listeners:
- |
query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
请问我该怎么办?
竖线字符 (|
) 启动 YAML 块标量。这意味着以下所有行都是文字字符串,不受进一步 YAML 解析的影响。
您的代码中发生了很多奇怪的事情,让我们回顾一下:
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
您在此处手动将映射转换为字符串列表。你为什么这样做?您希望最终的 YAML 文件包含键值对作为映射,因此您不应将它们转换为字符串列表。
让我们用一个简单的例子来讨论这里发生的事情:
假设我们有这个 java 地图:
Map<String, String> value = Map.of("foo", "bar");
如果我们直接将其序列化为 YAML,我们将得到
foo: bar
但如果我们通过您的方法进行管道传输,我们将得到
- "foo: bar"
即一个标量值的序列——因为我们手动将映射条目转换为字符串!这不是你想要的。
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
您在 getProperties()
的 return 值上调用 Arrays.asList
,其类型为 ArrayList<String>
,因此 asList
将 return 的值输入 List<ArrayList<String>>
,其中有一个条目是您构建的列表。目前还不清楚为什么要调用 Arrays.asList
除非你想要一个列表列表。根据所需的 YAML 输出,这不是您想要的。
现在让我们讨论一下 set
方法的作用。我不太了解 SimpleYAML,坦率地说,它的文档很糟糕,因为它基本上只包含自动生成的 API 文档。该方法的第一个参数名为path
,这意味着它不是一个简单的映射键。
显然 发生的是 List<ArrayList<String>>
值被转换为具有一个标量值的 YAML 序列,并且该标量值包含您生成的所有字符串值,由换行符分隔。没有适当的文档,就不可能说这是预期的行为还是错误。无论如何,这没有任何意义。
现在,实际的 YAML 在其根部包含一个具有一个条目的映射,其键是标量 listeners
。它的值是一个包含另一个映射的列表。这意味着,您实际想要序列化的类型是
Map<String, List<Map<String, Object>>>
我建议您简单地构建一个这种类型的值并使用 SnakeYAML API,它确实 proper documentation 关于其序列化系统的工作原理。无论如何,SimpleYAML 在幕后使用 SnakeYAML,似乎没有理由使用记录不详的 API 而不是记录良好的行为,而不是使用记录良好的行为。
您还可以创建自定义 Java class 而不是使用 Map
。然后键将变成 class 字段。
我想在 java 中编辑一个 yaml,(我正在编辑 BungeeCord 配置文件以创建一个系统,该系统启动具有由用户端口定义的 bungeecord 实例)但以一种精确的方式,我需要在 yaml 文件中准确地写这个:
listeners:
- query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
我做了一些非常相似的事情,但是有一个竖线阻止 BungeeCord 读取文件:
public class ProxyYaml {
HashMap<String, Object> entries = new HashMap<String, Object>();
public ProxyYaml() {
entries.put("query_port", 25577);
entries.put("motd", "Hey Guys");
entries.put("tab_list", "GLOBAL_PING");
entries.put("query_enabled", false);
entries.put("proxy_protocol", false);
entries.put("ping_passthrough", false);
entries.put("priorities", Arrays.asList("lobby"));
entries.put("bind_local_address", true);
entries.put("host", "0.0.0.0:25577");
entries.put("max_players", 1);
entries.put("tab_size", 60);
entries.put("force_default_server", false);
}
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
}
(我正在使用 SimpleYaml api 但如果需要我可以更改 api )
File propsProxyFile = new File(path + "config.yml");
YamlFile propsProxyYaml = new YamlFile(propsProxyFile);
try {
propsProxyYaml.load(propsProxyFile);
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
propsProxyYaml.save(propsProxyFile);
} catch (IOException | InvalidConfigurationException e) {
System.out.println(MainNetwork.logo + "Can't load proxy properties file");
return;
}
有代码输出(带竖线):
listeners:
- |
query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
请问我该怎么办?
竖线字符 (|
) 启动 YAML 块标量。这意味着以下所有行都是文字字符串,不受进一步 YAML 解析的影响。
您的代码中发生了很多奇怪的事情,让我们回顾一下:
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
您在此处手动将映射转换为字符串列表。你为什么这样做?您希望最终的 YAML 文件包含键值对作为映射,因此您不应将它们转换为字符串列表。
让我们用一个简单的例子来讨论这里发生的事情: 假设我们有这个 java 地图:
Map<String, String> value = Map.of("foo", "bar");
如果我们直接将其序列化为 YAML,我们将得到
foo: bar
但如果我们通过您的方法进行管道传输,我们将得到
- "foo: bar"
即一个标量值的序列——因为我们手动将映射条目转换为字符串!这不是你想要的。
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
您在 getProperties()
的 return 值上调用 Arrays.asList
,其类型为 ArrayList<String>
,因此 asList
将 return 的值输入 List<ArrayList<String>>
,其中有一个条目是您构建的列表。目前还不清楚为什么要调用 Arrays.asList
除非你想要一个列表列表。根据所需的 YAML 输出,这不是您想要的。
现在让我们讨论一下 set
方法的作用。我不太了解 SimpleYAML,坦率地说,它的文档很糟糕,因为它基本上只包含自动生成的 API 文档。该方法的第一个参数名为path
,这意味着它不是一个简单的映射键。
显然 发生的是 List<ArrayList<String>>
值被转换为具有一个标量值的 YAML 序列,并且该标量值包含您生成的所有字符串值,由换行符分隔。没有适当的文档,就不可能说这是预期的行为还是错误。无论如何,这没有任何意义。
现在,实际的 YAML 在其根部包含一个具有一个条目的映射,其键是标量 listeners
。它的值是一个包含另一个映射的列表。这意味着,您实际想要序列化的类型是
Map<String, List<Map<String, Object>>>
我建议您简单地构建一个这种类型的值并使用 SnakeYAML API,它确实 proper documentation 关于其序列化系统的工作原理。无论如何,SimpleYAML 在幕后使用 SnakeYAML,似乎没有理由使用记录不详的 API 而不是记录良好的行为,而不是使用记录良好的行为。
您还可以创建自定义 Java class 而不是使用 Map
。然后键将变成 class 字段。