Map转换为格式化的YAML字符串

yaml与java对象的互转

  1. yaml与java对象的互转有snakeyaml
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>lastest</version>
</dependency>

将map格式化为yml字符串

  1. 通过snakeyaml也可以将map对象转换为yml字符串,但是并不是很适用于平常的配置写法,比如对象会被{}包起来
  2. 通过自写代码将map对象转化为yml字符串
import lombok.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Getter
public class YamlTree {
    // 测试用例
    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("redis.host", "xxx");
        map.put("redis.port", "6379");
        map.put("redis.auth", "123456");
        map.put("redis.lettcue.key[0]", "a");
        map.put("redis.lettcue.key[1]", "b");
        map.put("redis.lettcue.obj[0].name", "tom");
        map.put("redis.lettcue.obj[0].age", "24");
        map.put("redis.lettcue.obj[1].name", "sam");
        map.put("redis.lettcue.obj[1].age", "21");
        YamlTree generate = YamlTree.generate(map);
        System.out.println(generate.format());
    }

    private static class Common {
        public static String[] fromNext(String[] unParseNodes) {
            if (unParseNodes.length > 1) {
                String[] copy = new String[unParseNodes.length - 1];
                for (int i = 1; i < unParseNodes.length; i++) {
                    copy[i - 1] = unParseNodes[i];
                }
                return copy;
            }
            return null;
        }

        public static void addTreeNode(List<YamlNode> nodes, YamlNode yamlNode) {
            boolean contains = false;
            for (YamlNode node : nodes) {
                if (node.getKey().equals(yamlNode.getKey())) {
                    contains = true;
                    break;
                }
            }
            if (!contains) {
                nodes.add(yamlNode);
            }
        }

        /**
         * 返回 是否是数组,数组下标,真实的key
         *
         * @param key
         * @return
         */
        public static Triple<Boolean, Integer, String> getRealKey(String key) {
            int index = StringUtils.indexOfAny(key, "[", "]");
            if (index >= 0) {
                int start = StringUtils.indexOf(key, "[");
                int end = StringUtils.indexOf(key, "]");
                int i = Integer.parseInt(StringUtils
                        .substring(key, start + 1, end));
                key = StringUtils.substring(key, 0, start);
                return Triple.of(true, i, key);
            }
            return Triple.of(false, null, key);
        }

        public static YamlNode findYamlNode(List<YamlNode> nodes, String key) {
            Triple<Boolean, Integer, String> triple = getRealKey(key);
            for (YamlNode node : nodes) {
                if (triple.getRight().equals(node.getKey())) {
                    return node;
                }
            }
            return null;
        }
    }

    public static YamlTree generate(Map<String, Object> map) {
        YamlTree yamlTree = new YamlTree();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String unParseKey = entry.getKey();
            String[] unParseNodes = StringUtils.split(unParseKey, ".");
            findAndAdd(unParseNodes, yamlTree.getNodes(), entry.getValue().toString());
        }
        return yamlTree;
    }

    private static void findAndAdd(String[] unParseNodes, List<YamlNode> nodes, String value) {
        Triple<Boolean, Integer, String> triple = Common.getRealKey(unParseNodes[0]);
        String start = triple.getRight();
        String[] nextUnParseNodes = Common.fromNext(unParseNodes);
        // 先找是否有节点
        YamlNode yamlNode = Common.findYamlNode(nodes, start);
        // 如果没有节点构造一个新节点
        if (yamlNode == null) {
            yamlNode = new YamlNode();
            yamlNode.setKey(unParseNodes[0]);
            yamlNode.autoSet(nextUnParseNodes, value, yamlNode);
            Common.addTreeNode(nodes, yamlNode);
        } else if (yamlNode.array) {
            yamlNode.autoSet(nextUnParseNodes, value, yamlNode);
            Common.addTreeNode(nodes, yamlNode);
        } else {
            // 先继续往下找
            findAndAdd(nextUnParseNodes, yamlNode.getNodes(), value);
        }
    }


    private List<YamlNode> nodes = new ArrayList<>();


    public String format() {
        StringBuilder stringBuilder = new StringBuilder();
        for (YamlNode node : nodes) {
            StringBuilder nodeStringBuilder = new StringBuilder();
            node.format(nodeStringBuilder, 0);
            stringBuilder.append(nodeStringBuilder.toString());
            stringBuilder.append("\n");
        }
        return stringBuilder.toString();
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private static class YamlObjectNode {
        private int index;
        private Map<String, String> value = new HashMap<>();
    }

    @Getter
    private static class YamlNode {

        private String key;

        private boolean array;

        // 临时下标
        private int index;

        private List<YamlObjectNode> objs = new ArrayList<>();

        private List<String> values = new ArrayList<>();

        private List<YamlNode> nodes = new ArrayList<>();

        public void setKey(String key) {
            Triple<Boolean, Integer, String> triple = Common.getRealKey(key);
            this.key = triple.getRight();
            this.array = triple.getLeft();
            if (triple.getMiddle() != null) {
                this.index = triple.getMiddle();
            }
        }

        public void setValue(String value) {
            this.values.add(value);
        }

        public YamlNode autoSet(String[] keys, String value, YamlNode last) {
            if (keys == null) {
                setValue(value);
                return this;
            }
            String start = keys[0];
            if (last != null && last.array) {
                YamlObjectNode yamlObjectNode = null;
                for (YamlObjectNode obj : objs) {
                    if (obj.getIndex() == index) {
                        yamlObjectNode = obj;
                        break;
                    }
                }
                boolean newObj = false;
                if (yamlObjectNode == null) {
                    yamlObjectNode = new YamlObjectNode();
                    newObj = true;
                }
                yamlObjectNode.setIndex(index);
                yamlObjectNode.getValue().put(start, value);
                if (newObj) {
                    objs.add(yamlObjectNode);
                }
            } else {
                YamlNode yamlNode = new YamlNode();
                yamlNode.setKey(start);
                YamlNode next = yamlNode.autoSet(Common.fromNext(keys), value, yamlNode);
                nodes.add(next);
            }
            return this;
        }

        private void fixBlank(StringBuilder stringBuilder, int level) {
            for (int i = 0; i < level; i++) {
                stringBuilder.append("  ");
            }
        }

        public void format(StringBuilder stringBuilder, int level) {
            // 补齐空白
            fixBlank(stringBuilder, level);
            // 加上key和冒号空格
            stringBuilder.append(this.getKey()).append(": ");
            if (isArray()) {
                // 如果是数组先换行
                stringBuilder.append("\n");
                // 换行后层级+1
                level++;
                // 检查是普通数组还是对象数组
                if (CollectionUtils.isEmpty(getValues())) {
                    // 对象数组
                    List<YamlObjectNode> objs = getObjs();
                    for (int i = 0; i < objs.size(); i++) {
                        // 补齐空白
                        fixBlank(stringBuilder, level);
                        stringBuilder.append("- ");
                        Map<String, String> map = objs.get(i).getValue();
                        int p = 1;
                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            if (p == 1) {
                                stringBuilder.append(entry.getKey() + ": " + entry.getValue()).append("\n");
                            } else {
                                fixBlank(stringBuilder, level);
                                stringBuilder.append("  ");
                                stringBuilder.append(entry.getKey() + ": " + entry.getValue()).append("\n");

                            }
                            p++;
                        }
                    }
                } else {
                    // 普通数组
                    for (String value : getValues()) {
                        // 补齐空白
                        fixBlank(stringBuilder, level);
                        stringBuilder.append("- ").append(value).append("\n");
                    }
                }
            } else {
                // 如果不是数组
                // 检查一下是否有下属节点
                if (!CollectionUtils.isEmpty(getValues())) {
                    stringBuilder.append(getValues().get(0)).append("\n");
                } else {
                    stringBuilder.append("\n");
                    List<YamlNode> nodes = getNodes();
                    level++;
                    for (YamlNode node : nodes) {
                        node.format(stringBuilder, level);
                    }
                }
            }
        }

    }

}

  1. 可能写得不怎么样,有很多优化的地方,仅作为记录
  • 关于map key的写法,是参考springcloud属性注入,在内存中的表达形式
posted @ 2021-01-17 16:51  OhOutOfMemoryError  阅读(1051)  评论(0)    收藏  举报