java yaml配置处理,yaml格式化,yaml节点增加,删除。多yaml合并

       多环境配置文件管理,增加一个配置属性,多套环境配置文件需同时增加,如果忘记了,那么就报错。对多环境配置文件进行管理,使用yaml作为文件时,就涉及到yaml的一些解析,修改,新增操作。

1. 环境依赖

       首先需要依赖snakeyaml,这里使用的是1.23版本

<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.23</version>
</dependency>

2. snakeyaml方法简单介绍

加载yaml对象:
       < T > T - loadAs(String,Class) :加载yaml对象,返回Class对象
       < T > Object - load(String):加载yaml对象,返回object对象
       iterable < object > - loadAll(String):加载yaml对象,返回迭代器
对象转为字符:
       String dump(object):object转化为字符串对象(只转化最外层yaml节点)
       String dumpAsMap(Map):Map对象转化为字符串对象

 String content = "nacos:\n" +
                "  dg: 889990\n" +
                "  addd: 444\n" +
                "  ggggg:\n" +
                "    aaaa: ''\n" +
                "spring:\n" +
                "  redis:\n" +
                "    path: 3344\n" +
                "ooo:\n" +
                "  pp: ''\n";
                
        Yaml yaml = new Yaml();
        Map map = yaml.loadAs(content, Map.class);
        System.out.println(map);
        
        Object load = yaml.load(content);
        System.out.println(load);
        
        Iterable<Object> objects = yaml.loadAll(content);
        for (Iterator<Object> it = objects.iterator(); it.hasNext();){
            Map<String,Object> object = (Map<String, Object>) it.next();
            System.out.println(object);
        }

        String dump = yaml.dump(map);
        System.out.println(dump);
        
        String s = yaml.dumpAsMap(map);
        System.out.println(s);

3. yaml处理思路

       snakeyaml解析获取到的Map集合是嵌套集合,{redis={host=6379,url=xxx}},这样的结构去做配置信息的变更比对是不方便的。
       因此先将此数据类型,转化为非嵌套Map集合,即{redis.host=6379,redis.url=xxx}的数据格式(Spring @value注解取值时,也是这种数据结构,IOC容器加载时,对配置文件进行解析,也是解析成这种格式)。
       解析为以上格式之后,再去对新旧配置进行节点的新增,删除判断就容易多了,提取以上Map集合的Key值放入List集合中,使用List集合的差集方法,即可得到新旧配置的差异对象。
       得到差异对象后,再将List对象使用Map容器承装(Map嵌套容器),将变更对象与原嵌套对象进行合并,再转化为yaml字符串,之后该输出到文件输出到文件,该存储就存储。

4. yaml字符串转非嵌套Map对象

输出结果:{nacos.ggggg.aaaa=, nacos.dg=889990, spring.redis.path=3344, ooo.pp=, nacos.addd=444}


private static final Map<String,String> cacheYamlMap = new HashMap<>();

public static void main(String[] args) {
    String content = "nacos:\n" +
            "  dg: 889990\n" +
            "  addd: 444\n" +
            "  ggggg:\n" +
            "    aaaa: ''\n" +
            "spring:\n" +
            "  redis:\n" +
            "    path: 3344\n" +
            "ooo:\n" +
            "  pp: ''\n";

    Yaml yaml = new Yaml();
    Iterable<Object> oldYaml = yaml.loadAll(content);
    analyzeYamlToList(oldYaml);
    System.out.println(cacheYamlMap);
}


public static void analyzeYamlToList(Iterable<Object> newYaml){
    for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
        Map<String,Object> object = (Map<String, Object>) it.next();
        parseYamlToMap(object,null);
    }
}

public static void parseYamlToMap(Map<String, Object> item, String key){
    item.forEach((k,v) -> {
        if(Objects.isNull(v))
            if (key == null)
                cacheYamlMap.put(k, "");
            else
                cacheYamlMap.put(key.concat(".").concat(k), "");
        else if (v instanceof LinkedHashMap)
            if (key == null)
                parseYamlToMap((Map<String, Object>) v,k);
            else
                parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
        else
        if (key == null)
            cacheYamlMap.put(k, v.toString());
        else
            cacheYamlMap.put(key.concat(".").concat(k), v.toString());
    });
}

5. List对象转嵌套yaml对象

输出结果:{redis={host={name=}, aaa={bbb=}}, nacos={server={name=}}}

 public static void main(String[] args) {
	 List<String> yaml = new ArrayList<>();
	   yaml.add("redis.host.name");
	   yaml.add("redis.aaa.bbb");
	   yaml.add("redis.aaa.bbb.ccc");
	   yaml.add("nacos.server.name");
	
	   Object map = transListToLinkMap(yaml);
	   System.out.println(map);
	}
	
	public static Object transListToLinkMap(List<String> yamlKey){
	   Map<String,Object> linkMap = new LinkedHashMap();
	   for (String val: yamlKey ) {
	       Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val);
	       addYamlMap(linkMap,map);
	   }
	
	   return linkMap;
	}
	
	private static Object transStringToLinkMap(String val){
	   int i = val.indexOf(".");
	   if(i < 0){
	       Map<String,Object> map = new LinkedHashMap<>();
	       map.put(val,"");
	       return map;
	   }
	
	   String key = val.substring(0, i);
	   String value = val.substring(i + 1);
	   Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value);
	
	   Map<String,Object> map = new LinkedHashMap<>();
	   map.put(key,linkedHashMap);
	   return map;
	}
	
	public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
	   for (Map.Entry<String,Object> val : addMap.entrySet()) {
	       boolean common = false;
	       for (Map.Entry<String,Object> obj : originMap.entrySet()) {
	           if (val.getKey().equals(obj.getKey())){
	               common = true;
	               try {
	                   Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
	                   Map<String,Object> addVal = (Map<String,Object>) val.getValue();
	                   addYamlMap(objVal,addVal);
	               }catch (Exception e){
	                   break;
	               }
	               break;
	           }
	       }
	       if(!common){
	           originMap.put(val.getKey(),val.getValue());
	       }
	   }
	}

6. 新旧yaml对比,yaml新增,删除属性

       懒得一个个demo贴了,下面贴出我写的yamlUtil类,需要什么功能自由组合。
       以下yaml属性新增的时候,默认值是""空字符串,未设默认值,需要默认值自行修改。


private static final Map<String,String> cacheYamlMap = new HashMap<>();

public enum ConstantEnum{
    ADD("add"),

    REMOVE("remove");

    private String code;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    ConstantEnum(String code){
        this.code = code;
    }

	public static ConstantEnum getInstance(String code){
    	for (ConstantEnum constantEnum: values()) {
            if(constantEnum.getCode().equals(code)){
                return constantEnum;
            }
        }
        return null;
    }
}

public static void main(String[] args) {
    //加两个attr节点下属性,删addd属性
    String oldContent = "nacos:\n" +
            "  dg: 889990\n" +
            "  addd: 444\n" +
            "spring:\n" +
            "  redis:\n" +
            "    path: 3344\n";
    String newContent = "nacos:\n" +
            "  dg: 889990\n" +
            "spring:\n" +
            "  redis:\n" +
            "    path: 3344\n" +
            "    attr:\n" +
            "      name: 3333\n" +
            "      value: 4444";

    Yaml yaml = new Yaml();
    List<String> addAttr = YamlParserUtil.compareAndGetDiffAttr(oldContent, newContent, YamlParserUtil.ConstantEnum.ADD);
    List<String> removeAttr = YamlParserUtil.compareAndGetDiffAttr(oldContent, newContent, YamlParserUtil.ConstantEnum.REMOVE);
    Map<String,Object> addMap = (Map<String, Object>) YamlParserUtil.transListToLinkMap(addAttr);
    Map<String,Object> removeMap = (Map<String, Object>) YamlParserUtil.transListToLinkMap(removeAttr);

    Map originMap = yaml.loadAs(oldContent, Map.class);
    YamlParserUtil.addAndRemoveYaml(originMap,removeMap,addMap);
    String dump = yaml.dumpAsMap(originMap);
    System.out.println(dump);
}

/**
 * trans key list to map
 * demo: spring.redis.host to {spring={redis={host=}}}
 * @param yamlKey
 * @return
 */
public static Object transListToLinkMap(List<String> yamlKey){
    Map<String,Object> linkMap = new LinkedHashMap();
    for (String val: yamlKey ) {
        Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val);
        addYamlMap(linkMap,map);
    }

    return linkMap;
}

public static void addAndRemoveYaml(Map<String,Object> originMap,Map<String,Object> removeMap,Map<String,Object> addMap){
    removeYamlMap(originMap,removeMap);
    addYamlMap(originMap,addMap);
}

public static boolean removeYamlMap(Map<String, Object> originMap, Map<String, Object> removeMap){
    for (Map.Entry<String,Object> val : removeMap.entrySet()) {
        for (Map.Entry<String,Object> obj :originMap.entrySet()) {
            if(val.getKey().equals(obj.getKey())){
                try {
                    Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
                    Map<String,Object> addVal = (Map<String,Object>) val.getValue();
                    if(removeYamlMap(objVal,addVal)){
                        originMap.remove(val.getKey());
                        break;
                    }
                }catch (Exception e){
                    originMap.remove(val.getKey());
                    break;
                }
            }
        }
    }
    if(originMap==null || originMap.isEmpty()){
        return true;
    }
    return false;
}

/**
 * {spring={redis={host=}}} | {spring={rabbit={host=}}} merge to {spring={redis={host=},rabbit={host=}}}
 *
 * Combine the addMap collection, do not allow the same key value to be overwritten
 * @param originMap
 * @param addMap
 */
public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
    for (Map.Entry<String,Object> val : addMap.entrySet()) {
        boolean common = false;
        for (Map.Entry<String,Object> obj : originMap.entrySet()) {
            if (val.getKey().equals(obj.getKey())){
                common = true;
                try {
                    Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
                    Map<String,Object> addVal = (Map<String,Object>) val.getValue();
                    addYamlMap(objVal,addVal);
                }catch (Exception e){
                    break;
                }
                break;
            }
        }
        if(!common){
            originMap.put(val.getKey(),val.getValue());
        }
    }
}

/**
 * spring.redis.host to {spring={redis={host=}}}
 *
 * trans string to map,Parse the yaml string
 * @param val
 * @return
 */
private static Object transStringToLinkMap(String val){
    int i = val.indexOf(".");
    if(i < 0){
        Map<String,Object> map = new LinkedHashMap<>();
        map.put(val,"");
        return map;
    }

    String key = val.substring(0, i);
    String value = val.substring(i + 1);
    Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value);

    Map<String,Object> map = new LinkedHashMap<>();
    map.put(key,linkedHashMap);
    return map;
}

/**
 *
 * compare yaml content get diff key list
 * @param oldContent
 * @param newContent
 * @return
 */
public static List<String> compareAndGetDiffAttr(String oldContent, String newContent,ConstantEnum type){
    Yaml yaml = new Yaml();
    Iterable<Object> oldYaml = yaml.loadAll(oldContent);
    List<String> oldKey = analyzeYamlToList(oldYaml);

    Iterable<Object> newYaml = yaml.loadAll(newContent);
    List<String> recent = analyzeYamlToList(newYaml);

    if(ConstantEnum.ADD.equals(type)){
        List<String> compareList = new ArrayList<>(recent);
        compareList.removeAll(oldKey);
        return compareList;
    }else{
        List<String> compareList = new ArrayList<>(oldKey);
        compareList.removeAll(recent);
        return compareList;
    }
}

public static List<String> analyzeYamlToList(Iterable<Object> newYaml){
    for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
        Map<String,Object> object = (Map<String, Object>) it.next();
        parseYamlToMap(object,null);
    }

    List<String> keyList = new ArrayList<>();
    cacheYamlMap.forEach((key,val)->{ keyList.add(key); });

    cacheYamlMap.clear();
    return keyList;
}

/**
 *  {spring={redis={host=},rabbit={host=}}} to {spring.redis.host= ,spring.rabbit.host=}
 *
 * trans yaml map to key map
 * @param item
 * @param key
 */
public static void parseYamlToMap(Map<String, Object> item, String key){
    item.forEach((k,v) -> {
        if(Objects.isNull(v))
            if (key == null)
                cacheYamlMap.put(k, "");
            else
                cacheYamlMap.put(key.concat(".").concat(k), "");
        else if (v instanceof LinkedHashMap)
            if (key == null)
                parseYamlToMap((Map<String, Object>) v,k);
            else
                parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
        else
        if (key == null)
            cacheYamlMap.put(k, v.toString());
        else
            cacheYamlMap.put(key.concat(".").concat(k), v.toString());
    });
}

7.新增属性属性值不为空

不同的业务需求,面向的yaml对象不一样,要的效果不一样,下面的代码对比标题6,做了一些变动,以及注释,各位看官可在次基础上自由发挥。(6的升级版本)


    private static final Map<String,String> cacheYamlMap = new HashMap<>();

    public enum ConstantEnum{
        ADD("add"),

        REMOVE("remove");

        private String code;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        ConstantEnum(String code){
            this.code = code;
        }

        public static ConstantEnum getInstance(String code){
            for (ConstantEnum constantEnum: values()) {
                if(constantEnum.getCode().equals(code)){
                    return constantEnum;
                }
            }
            return null;
        }
    }

    public static void main(String[] args) {
        //加两个attr节点下属性,删addd属性
        String oldContent = "nacos:\n" +
                "  dg: 889990\n" +
                "  addd: 444\n" +
                "spring:\n" +
                "  redis:\n" +
                "    path: 3344\n";
        String newContent = "nacos:\n" +
                "  dg: 889333333990\n" +
                "spring:\n" +
                "  redis:\n" +
                "    path: 3344\n" +
                "    attr:\n" +
                "      name: 3333\n" +
                "      value: 4444";

        Yaml yaml = new Yaml();
        //以就模板为基准模板,对比新模板,筛选出新增的属性
        List<Map<String, String>> addAttr = compareAndGetDiffAttr(oldContent, newContent, ConstantEnum.ADD);
        //以旧模板为基准模板,对比新模板,筛选删除属性
        List<String> removeAttr = compareAndGetDiffAttr(oldContent, newContent, ConstantEnum.REMOVE);

        //将筛选出的属性集合,转化为linkMap格式
        Map<String,Object> addMap = (Map<String, Object>) transMapListToLinkMap(addAttr);
        Map<String,Object> removeMap = (Map<String, Object>) transListToLinkMap(removeAttr);

        //以旧模板值为标准值,除了增加的属性值,其他均为旧模板值
        Map originMap = yaml.loadAs(oldContent, Map.class);
        //对旧模板进行新增,删除属性操作
        addAndRemoveYaml(originMap,removeMap,addMap);
        String dump = yaml.dumpAsMap(originMap);
        System.out.println(dump);
    }

    /**
     * trans key list to map
     * demo: spring.redis.host to {spring={redis={host=}}}
     * @param yamlKey
     * @return
     */
    public static Object transListToLinkMap(List<String> yamlKey){
        Map<String,Object> linkMap = new LinkedHashMap();
        for (String val: yamlKey ) {
            Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val,null);
            addYamlMap(linkMap,map);
        }

        return linkMap;
    }

    public static Object transMapListToLinkMap(List<Map<String, String>> yamlKey){
        Map<String,Object> linkMap = new LinkedHashMap();
        for (Map<String, String> val: yamlKey ) {
            for (Map.Entry<String,String> value :val.entrySet()) {
                Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(value.getKey(),value.getValue());
                addYamlMap(linkMap,map);
            }
        }

        return linkMap;
    }

    public static void addAndRemoveYaml(Map<String,Object> originMap,Map<String,Object> removeMap,Map<String,Object> addMap){
        removeYamlMap(originMap,removeMap);
        addYamlMap(originMap,addMap);
    }

    public static boolean removeYamlMap(Map<String, Object> originMap, Map<String, Object> removeMap){
        for (Map.Entry<String,Object> val : removeMap.entrySet()) {
            for (Map.Entry<String,Object> obj :originMap.entrySet()) {
                if(val.getKey().equals(obj.getKey())){
                    try {
                        Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
                        Map<String,Object> addVal = (Map<String,Object>) val.getValue();
                        if(removeYamlMap(objVal,addVal)){
                            originMap.remove(val.getKey());
                            break;
                        }
                    }catch (Exception e){
                        originMap.remove(val.getKey());
                        break;
                    }
                }
            }
        }
        if(originMap==null || originMap.isEmpty()){
            return true;
        }
        return false;
    }

    /**
     * {spring={redis={host=}}} | {spring={rabbit={host=}}} merge to {spring={redis={host=},rabbit={host=}}}
     *
     * Combine the addMap collection, do not allow the same key value to be overwritten
     * @param originMap
     * @param addMap
     */
    public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
        //遍历新旧两个嵌套集合,将值,属性进行合并
        for (Map.Entry<String,Object> val : addMap.entrySet()) {
            boolean common = false;
            for (Map.Entry<String,Object> obj : originMap.entrySet()) {
                if (val.getKey().equals(obj.getKey())){
                    common = true;
                    try {
                        Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
                        Map<String,Object> addVal = (Map<String,Object>) val.getValue();
                        addYamlMap(objVal,addVal);
                    }catch (Exception e){
                        break;
                    }
                    break;
                }
            }
            if(!common){
                originMap.put(val.getKey(),val.getValue());
            }
        }
    }

    /**
     * spring.redis.host to {spring={redis={host=}}}
     *
     * trans string to map,Parse the yaml string
     * @param val
     * @return
     */
    private static Object transStringToLinkMap(String yamlKey,String val){
        int i = yamlKey.indexOf(".");
        if(i < 0){
            Map<String,Object> map = new LinkedHashMap<>();
            map.put(yamlKey,val);
            return map;
        }

        String key = yamlKey.substring(0, i);
        String value = yamlKey.substring(i + 1);
        Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value,val);

        Map<String,Object> map = new LinkedHashMap<>();
        map.put(key,linkedHashMap);
        return map;
    }

    /**
     *
     * compare yaml content get diff key list
     * @param oldContent
     * @param newContent
     * @return
     */
    public static List compareAndGetDiffAttr(String oldContent, String newContent,ConstantEnum type){
        Yaml yaml = new Yaml();
        //获取旧模板的key集合
        Iterable<Object> oldYaml = yaml.loadAll(oldContent);
        List<String> oldKey = analyzeYamlToList(oldYaml);

        Iterable<Object> newYaml = yaml.loadAll(newContent);

        //新增比较特殊,需要保留原值,
        if(ConstantEnum.ADD.equals(type)){
            //获取新模板的Key value集合
            List<Map<String, String>> list = analyzeYamlToListMap(newYaml);
            Iterator<Map<String, String>> iterator = list.iterator();

            //遍历,与旧模板进行对比,删除掉相同key的元素,留下的就是新增的
            while (iterator.hasNext()){
                //以新模板为基准对比
                for (Map.Entry<String,String> value :iterator.next().entrySet()) {
                    for (String key :oldKey) {
                        if(key.equals(value.getKey())){
                            iterator.remove();
                            break;
                        }
                    }
                }
            }

            return list;
        }else{
            //旧模板与新模板进行取差集,得到旧模板与新模板的差异属性,即需要删除的属性
            List<String> recent = analyzeYamlToList(newYaml);
            //以旧模板为基准
            List<String> compareList = new ArrayList<>(oldKey);
            compareList.removeAll(recent);
            return compareList;
        }
    }

    public static List<String> analyzeYamlToList(Iterable<Object> newYaml){
        //将yaml遍历器中的嵌套集合转化为单个KEY VALUE对应的Map集合,存放至静态变量
        for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
            Map<String,Object> object = (Map<String, Object>) it.next();
            parseYamlToMap(object,null);
        }

        //将上一个步骤存放的集Map集合提取成List集合,提取单个Key值
        List<String> keyList = new ArrayList<>();
        cacheYamlMap.forEach((key,val)->{ keyList.add(key); });

        cacheYamlMap.clear();
        return keyList;
    }

    public static List<Map<String,String>> analyzeYamlToListMap(Iterable<Object> newYaml){
        //将yaml遍历器中的嵌套集合转化为单个KEY VALUE对应的Map集合,存放至静态变量
        for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
            Map<String,Object> object = (Map<String, Object>) it.next();
            parseYamlToMap(object,null);
        }
        //将上一个步骤存放的集Map集合提取成List集合,并且拆分为单个Map,放入集合(便于后续便利)
        List<Map<String,String>> keyList = new ArrayList<>();
        cacheYamlMap.forEach((key,val)->{
            Map<String,String> map = new HashMap<>();
            map.put(key,val);
            keyList.add(map);
        });

        cacheYamlMap.clear();
        return keyList;
    }
    /**
     *  {spring={redis={host=},rabbit={host=}}} to {spring.redis.host= ,spring.rabbit.host=}
     *
     * trans yaml map to key map
     * @param item
     * @param key
     */
    public static void parseYamlToMap(Map<String, Object> item, String key){
        //将嵌套Map集合,转化为单个Key value对应的属性集合
        item.forEach((k,v) -> {
            if(Objects.isNull(v))
                if (key == null)
                    cacheYamlMap.put(k, "");
                else
                    cacheYamlMap.put(key.concat(".").concat(k), v.toString());
            else if (v instanceof LinkedHashMap)
                if (key == null)
                    parseYamlToMap((Map<String, Object>) v,k);
                else
                    parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
            else
            if (key == null)
                cacheYamlMap.put(k, v.toString());
            else
                cacheYamlMap.put(key.concat(".").concat(k), v.toString());
        });
    }


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值