You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java在YAML文件中生成字符串格式的多端口配置

解决方案

问题根源

你遇到的YAML格式断裂问题,核心是手动拼接links部分的字符串并直接写入文件,这会干扰SnakeYAML的正常序列化输出,导致后续内容格式错乱。另外之前尝试的Representer配置没有正确应用到YAML实例中,导致端口字符串无法被强制引号包裹。

修正步骤及代码

  1. 移除手动拼接links的逻辑,改用SnakeYAML自动序列化links列表,保证YAML结构一致性。
  2. 配置自定义Representer,强制所有字符串类型的标量使用双引号(或单引号)包裹。
  3. 将ports数组改为List,和Bean中的类型保持一致,避免序列化时的类型转换问题。

修正后的完整代码:

import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class GenerateYamlFileImpl implements GenerateYamlFile {

    private static final Logger logger = LogManager.getLogger(GenerateYamlFileImpl.class);

    public void writeYamlfile(Container container, File file) {
        try (FileWriter writer = new FileWriter(file.getPath() + LocalDateTime.now() + FXMLPageConstants.FILE_TYPE)) {
            DumperOptions options = new DumperOptions();
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            options.setPrettyFlow(true);

            // 配置自定义Representer,强制字符串用双引号包裹
            Representer representer = new Representer(options) {
                @Override
                protected Node representScalar(Tag tag, String value) {
                    // 对所有字符串标量使用双引号
                    return super.representScalar(tag, value, DumperOptions.ScalarStyle.DOUBLE_QUOTED);
                }
            };

            // 使用自定义Representer创建YAML实例
            Yaml yaml = new Yaml(representer, options);
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("name", container.getName());

            Map<String, Object> topology = new LinkedHashMap<>();
            Map<String, Object> nodes = new LinkedHashMap<>();
            for (Map.Entry<String, NodesProperties> entry : container.getTopology().getNodes().entrySet()) {
                Map<String, Object> nodeDetails = new LinkedHashMap<>();
                NodesProperties nodeProps = entry.getValue();
                nodeDetails.put("kind", nodeProps.getKind());
                nodeDetails.put("image", nodeProps.getImage());
                if (nodeProps.getGroup() != null && !nodeProps.getGroup().isBlank()) {
                    nodeDetails.put("group", nodeProps.getGroup());
                }
                if (nodeProps.getStartupConfig() != null && !nodeProps.getStartupConfig().isBlank()) {
                    nodeDetails.put("startup-config", nodeProps.getStartupConfig());
                }
                if (nodeProps.getPorts() != null && !nodeProps.getPorts().isEmpty()) {
                    // 将ports转为带":22"后缀的List<String>,保持类型一致
                    List<String> ports = nodeProps.getPorts().stream()
                            .map(port -> port + ":" + "22")
                            .collect(Collectors.toList());
                    nodeDetails.put("ports", ports);
                }
                nodes.put(entry.getKey(), nodeDetails);
            }
            topology.put("nodes", nodes);

            // 处理links,转为SnakeYAML可序列化的结构,不再手动拼接
            List<Map<String, Object>> linksList = container.getTopology().getLinks().stream()
                    .map(link -> {
                        Map<String, Object> linkMap = new LinkedHashMap<>();
                        linkMap.put("endpoints", link.getEndpoints());
                        return linkMap;
                    })
                    .collect(Collectors.toList());
            topology.put("links", linksList);

            data.put("topology", topology);
            // 一次性序列化所有数据到文件,避免手动写入破坏格式
            yaml.dump(data, writer);

            logger.info("YAML file generated successfully: " + file.getPath());
        } catch (IOException e) {
            logger.error("Error while writing YAML file", e);
        }
    }
}

关键修改说明

  • 自定义Representer:通过重写representScalar方法,强制所有字符串标量使用双引号包裹,确保端口字符串(如2000:22)被正确识别为字符串类型。
  • 移除手动links拼接:将links转为List<Map>结构,让SnakeYAML自动序列化,保证整个YAML文件的结构完整性,不会出现格式断裂。
  • ports改用List:和Bean中的List<String>类型保持一致,避免数组序列化时可能出现的异常,同时让SnakeYAML能正确应用Representer的规则。

生成效果

修改后生成的YAML会符合预期格式:

name: "example-container"
topology:
  nodes:
    node1:
      kind: "server"
      image: "ubuntu:latest"
      ports:
      - "2000:22"
      - "3000:80"
  links:
  - endpoints: ["node1", "node2"]

内容的提问来源于stack exchange,提问作者BEdits

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:05:00