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

如何读取指定结构文本文件并映射到Java对象后转YAML?

多Project场景下Java实体映射到YAML的错误修复

需求说明

逐行读取指定结构的文本文件,将内容填充到自定义的Parameter、Project等嵌套Java实体类中,最终转换为指定格式的YAML文件,禁止硬编码赋值。

待读取文本文件结构

  • context:dev
  • region:asia
  • lob:all
  • projects: (This is a list of project)
  • name:hub
  • topics: (List of Topic inside projects)
  • dataType:0
  • name:cdc
  • plan:dev-rack
  • dataType:0.dlq
  • name:cdc
  • plan:rack
  • dataType:0
  • name:raw
  • plan:dev
  • schemas:
  • value.schema.file:-data-hub.raw.0-value-v1.json
  • value.format:JSON
  • dataType:Produce.dlq
  • name:raw
  • plan:ack
  • schemas:
  • value.schema.file:hub.raw.0-value-v1.json
  • value.format:JSON
  • dataType:0
  • name:dom
  • plan:dev
  • schemas:
  • value.schema.file:dom.0-value-v1.json
  • value.format:JSON
  • dataType:Produce.dlq
  • name:dom
  • plan:de
  • schemas:
  • value.schema.file:0-value-v1.json
  • value.format:JSON

已定义Java实体类

Parameter类

@Getter
@Setter
@ToString
public class Parameter {
    private String context;
    private String region;
    private String lob;
    private List<Project> projects; // 修正原字段名"Project"不符合Java命名规范问题
}

Project类

@Getter
@Setter
@ToString
public class Project {
    private String name;
    private List<Topic> topics;
}

Topic类

@Getter
@Setter
@ToString
public class Topic {
    private String dataType;
    private String name;
    private String plan;
    private Schemas schemas;

    public boolean checkDlq(String dataType) {
        dataType = getDataType();
        return dataType.contains("dlq");
    }
}

Schemas类

@Getter
@Setter
@ToString
public class Schemas {
    private Value value;
}

Value类

@Getter
@Setter
@ToString
public class Value {
    private Schema schema;
    private String format;
}

Schema类

@Getter
@Setter
@ToString
public class Schema {
    private String file;
}

目标YAML格式示例

context: "dev"
region: "asia"
lob: "all"
projects:
  - name: "hub"
    topics:
    - dataType: "0"
      name: "cdc"
      plan: "devrack"
    - dataType: "0.dlq"
      name: "cdc"
      plan: "dev-bronze-rack"  
    - dataType: "0"
      name: "raw"
      plan: "rack"
      schemas:
        value.schema.file: "hub.raw.0-value-v1.json"
        value.format: "JSON" 
    - dataType: "Produce.dlq"
      name: "raw"
      plan: "devrack"
      schemas:
        value.schema.file: "raw.0-value-v1.json"
        value.format: "JSON"
    - dataType: "0"
      name: "dom"
      plan: "rack"
      schemas:
        value.schema.file: "0-value-v1.json"
        value.format: "JSON"
    - dataType: "0.dlq"
      name: "dom"
      plan: "dev"
      schemas:
        value.schema.file: "v1.json"
        value.format: "JSON"

问题描述

当前实现的YamlProcessor类在单个Project场景下可正常工作,但存在多个Project时,无法创建独立的Project列表,所有Topic会被添加到同一个Project的topics集合中。

现有问题代码

public class YamlProcessor {

    public void addToObject() throws IOException {

        Parameter parameter = new Parameter();
        FileReader fileReader = new FileReader("C:/Users/zk72/Desktop/schema.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line = bufferedReader.readLine();

        List<Topic> addTopic = new ArrayList<>();
        List<Project> addProject = new ArrayList<>();
        //Single Variable
        Map<String, String> singleVariable = new HashMap<>();
        //For Project list - eg-> project1 , list of project
        Map<String, Map<String,String>> projects = new HashMap<>();
        Map<String, Map<String,Map<String,String>>> ps = new HashMap<>();
        //For Topics List - eg-> topic1, list of project
        Map<String, Map<String, String>> topics = new HashMap<>();

        while (line != null) {
            String s[] = line.split(":");
            switch (s[0]) {
                case Constants.CONTEXT:
                    singleVariable.put(s[0],s[1]);
                    break;

                case Constants.REGION:
                    singleVariable.put(s[0],s[1]);
                    break;

                case Constants.LOB:
                    singleVariable.put(s[0],s[1]);
                    break;

                case Constants.PROJECTS:
                    Map<String, String> project = new HashMap<>();
                    Map<String, String> topic = new HashMap<>();
                    int projectCount = 1;
                    while ((line = bufferedReader.readLine()) != null) {
                        String ss[] = line.split(":");
                        if (ss[0].equals(Constants.NAME)) {
                            if (!project.isEmpty() && project != null) {
                                projects.put("project"+projectCount, project);
                                projectCount++;
                                project = new HashMap<>();
                                project.put(ss[0],ss[1]);
                            }else {
                                project.put(ss[0],ss[1]);
                            }
                        }else if (ss[0].equals(Constants.TOPICS)) {
                            int topicCount = 1;
                            while((line = bufferedReader.readLine()) != null){
                                String str[] = line.split(":");
                                if (str[0].equals(Constants.DATA_TYPE) && !str[0].equals(Constants.NAME)) {
                                    if(!topic.isEmpty() && topic !=null){
                                        topics.put("topic"+topicCount, topic);
                                        topicCount++;
                                        topic = new HashMap<>();
                                        topic.put(str[0],str[1]);
                                    } else {
                                        topic.put(str[0],str[1]);
                                    }
                                } else {
                                    if(str.length > 1)
                                        topic.put(str[0],str[1]);
                                }

                            }
                            topicCount++;
                            topics.put("topic"+topicCount, topic);
                        }
                    }
                    projectCount++;
                    projects.put("project"+projectCount, project);
            }
            line = bufferedReader.readLine();
        }

        parameter.setContext(singleVariable.get(Constants.CONTEXT));
        parameter.setRegion(singleVariable.get(Constants.REGION));
        parameter.setLob(singleVariable.get(Constants.LOB));

        for (Map.Entry<String, Map<String,String>> entry: topics.entrySet()) {
            Topic topic = new Topic();
            topic.setDataType(entry.getValue().get(Constants.DATA_TYPE));
            topic.setName(entry.getValue().get(Constants.NAME));
            topic.setPlan(entry.getValue().get(Constants.PLAN));

            Schemas schemas = new Schemas();
            Value value = new Value();
            Schema schema = new Schema();

            schema.setFile(entry.getValue().get(Constants.VALUE_SCHEMA_FILE));
            value.setSchema(schema);
            value.setFormat(entry.getValue().get(Constants.VALUE_FORMAT));
            schemas.setValue(value);

            topic.setSchemas(schemas);
            addTopic.add(topic);
        }

        for (Map.Entry<String, Map<String, String>> entry: projects.entrySet()) {
            Project project = new Project();
            project.setName(entry.getValue().get(Constants.NAME));
            project.setTopics(addTopic);
            addProject.add(project);
        }

        parameter.setProjects(addProject);

        System.out.println(parameter.toString());

        DumperOptions options = new DumperOptions();
        options.setIndent(2);
        options.setPrettyFlow(true);
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        PrintWriter writer = new PrintWriter(new File("./src/main/resources/topology3.yml"));
        Yaml yaml = new Yaml(options);
        yaml.dump(parameter, writer);
        bufferedReader.close();

    }

    public static void main(String[] args) throws IOException {

        YamlProcessor processor = new YamlProcessor();
        processor.addToObject();
    }
}

解决方案

问题根源

  1. 全局addTopic列表被所有Project共享,导致每个Project的topics集合都是同一批数据。
  2. 解析逻辑通过中间Map中转,没有直接维护Project与Topic的归属关系,无法区分Topic所属的Project。

修复后的代码实现

重构解析逻辑,直接操作实体类,在读取文本时实时维护Project和其对应的Topic列表:

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.File;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class YamlProcessor {

    public void addToObject() throws IOException {
        Parameter parameter = new Parameter();
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader("C:/Users/zk72/Desktop/schema.txt"))) {
            String line;
            List<Project> projectList = new ArrayList<>();
            Project currentProject = null;
            List<Topic> topicList = null;
            Topic currentTopic = null;
            Schemas currentSchemas = null;
            Value currentValue = null;

            while ((line = bufferedReader.readLine()) != null) {
                line = line.trim();
                if (line.isEmpty()) {
                    continue;
                }
                String[] parts = line.split(":", 2);
                if (parts.length < 2) {
                    // 处理无值的标记行
                    switch (parts[0]) {
                        case Constants.PROJECTS:
                            projectList = new ArrayList<>();
                            break;
                        case Constants.TOPICS:
                            if (currentProject != null) {
                                topicList = new ArrayList<>();
                                currentProject.setTopics(topicList);
                            }
                            break;
                        case Constants.SCHEMAS:
                            if (currentTopic != null) {
                                currentSchemas = new Schemas();
                                currentValue = new Value();
                                currentSchemas.setValue(currentValue);
                                currentTopic.setSchemas(currentSchemas);
                            }
                            break;
                    }
                    continue;
                }
                String key = parts[0].trim();
                String value = parts[1].trim();

                switch (key) {
                    case Constants.CONTEXT:
                        parameter.setContext(value);
                        break;
                    case Constants.REGION:
                        parameter.setRegion(value);
                        break;
                    case Constants.LOB:
                        parameter.setLob(value);
                        break;
                    case Constants.NAME:
                        // 判断是Project还是Topic的名称
                        if (currentProject == null || (topicList != null && currentTopic != null)) {
                            // 保存当前Project并创建新的
                            if (currentProject != null) {
                                projectList.add(currentProject);
                            }
                            currentProject = new Project();
                            currentProject.setName(value);
                            topicList = null;
                            currentTopic = null;
                        } else {
                            // 创建新的Topic并加入当前Project的列表
                            currentTopic = new Topic();
                            currentTopic.setName(value);
                            if (topicList != null) {
                                topicList.add(currentTopic);
                            }
                        }
                        break;
                    case Constants.DATA_TYPE:
                        if (currentTopic != null) {
                            currentTopic.setDataType(value);
                        }
                        break;
                    case Constants.PLAN:
                        if (currentTopic != null) {
                            currentTopic.setPlan(value);
                        }
                        break;
                    case Constants.VALUE_SCHEMA_FILE:
                        if (currentValue != null) {
                            Schema schema = new Schema();
                            schema.setFile(value);
                            currentValue.setSchema(schema);
                        }
                        break;
                    case Constants.VALUE_FORMAT:
                        if (currentValue != null) {
                            currentValue.setFormat(value);
                        }
                        break;
                }
            }
            // 加入最后一个未保存的Project
            if (currentProject != null) {
                projectList.add(currentProject);
            }
            parameter.setProjects(projectList);

            // 输出到YAML文件
            DumperOptions options = new DumperOptions();
            options.setIndent(2);
            options.setPrettyFlow(true);
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            try (PrintWriter writer = new PrintWriter(new File("./src/main/resources/topology3.yml"))) {
                Yaml yaml = new Yaml(options);
                yaml.dump(parameter, writer);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        YamlProcessor processor = new YamlProcessor();
        processor.addToObject();
    }

    // 常量定义
    public static class Constants {
        public static final String CONTEXT = "context";
        public static final String REGION = "region";
        public static final String LOB = "lob";
        public static final String PROJECTS = "projects";
        public static final String NAME = "name";
        public static final String TOPICS = "topics";
        public static final String DATA_TYPE = "dataType";
        public static final String PLAN = "plan";
        public static final String SCHEMAS = "schemas";
        public static final String VALUE_SCHEMA_FILE = "value.schema.file";
        public static final String VALUE_FORMAT = "value.format";
    }
}

修复说明

  1. 移除冗余中间Map,直接在读取文本时创建并维护实体对象的关联关系,确保Topic归属正确的Project。
  2. 通过currentProject、currentTopic等变量跟踪当前解析的实体,明确层级关系。
  3. 处理无值标记行,正确触发实体层级的初始化。
  4. 修正Parameter类字段名的命名规范,避免序列化异常。
  5. 使用try-with-resources自动关闭流,提升代码健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:55:48