yaml、yml内容属性重复校验,对比
1. 依赖包
首先需要依赖snakeyaml,这个包解析{} 、json、数组形式的配置会识别错误。
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
</dependency>
2. 单个文件主属性重复检测
因为yaml.loadsAs会自动覆盖,或者仅读取一个重复属性,因此,借用snakeyaml做单个文件重复检测是不现实的。只能通过空格符,等一些yaml格式独有的特点来判断,这里借用空格来判断第一节点属性的重复(后续子节点通过这种方式无法判断,因此这里也只做了主属性判断)。
/**
* @Author:Huey
* @Date: 2022/4/28 0028 18:11
* @Description: 检查,单个文件一级属性重复自检
* @params:
* @return
*/
public static List<String> checkRepeatAttr(String content){
content = content.replace("\n","@%");
String[] data = content.split("@%");
//获取所有的主属性值
List<String> indexAttr = new ArrayList<>();
for (int i = 0; i < data.length; i++) {
int index = data[i].indexOf(" ");
//只要不是在首位出现的空格,name就是主属性
if(index != 0){
indexAttr.add(data[i]);
}
}
List<String> repeatList = new ArrayList<>();
//找出去重复属性值
for (int i = 0; i < indexAttr.size(); i++) {
String attr = indexAttr.get(i);
for (int j = i + 1; j < indexAttr.size(); j++) {
String compareAttr = indexAttr.get(j);
if(attr.equals(compareAttr)){
repeatList.add(attr);
}
}
}
return repeatList;
}
3. 两个yaml属性重复检查 / 主副配置文件重复属性检查
这里借用snakeyaml,对从一级节点开始一直重复的节点进行检查,最终返回结果精确至最后一级重复的节点名称。
/**
* @Author:Huey
* @Date: 2022/4/28 0028 18:11
* @Description: 检查,对比主副文件重复属性
* @params:
* @return
*/
public static List<String> checkRepeatAttr(String content, String compareContent){
List<String> list = new ArrayList<>();
if(StringUtils.isBlank(content) || StringUtils.isBlank(compareContent)){
return list;
}
Yaml yaml = new Yaml();
Map<String,Object> originMap = yaml.loadAs(content, Map.class);
Map<String,Object> compareMap = yaml.loadAs(compareContent, Map.class);
extracted(originMap, compareMap,null,list);
return list;
}
//递归获取相同属性
private static void extracted(Map<String, Object> originMap, Map<String, Object> compareMap,String repeatKey, List<String> list) {
if(originMap == null || compareMap == null){
return;
}
for (Map.Entry<String,Object> compare : compareMap.entrySet()) {
//每一个递归路径需要一个完整的Key值路径,key值不变的话会路径混乱
String key = repeatKey;
for (Map.Entry<String,Object> map : originMap.entrySet()) {
//如果节点相同,则继续进行递归,找寻到下一级
if(map.getKey().equals(compare.getKey())){
Map<String, Object> map1;
Map<String, Object> map2;
key = null == key ? map.getKey() : key + ":" +map.getKey();
try {
map1 = (Map<String, Object>) map.getValue();
map2 = (Map<String, Object>) compare.getValue();
//value值为null时,也能正常转化
if(map1 == null || map2 == null){
list.add(key);
}
}catch (Exception e){
//如果报错了,说明下一级有值出现了,直接返回目前为止相同的节点
list.add(key);
continue;
}
extracted(map1,map2,key,list);
break;
}
}
}
}
}
//返回结果示例:
//[spring:datasource:initialSize, ...]
public static void main(String[] args) {
String contentS = "#数据源连接数配置\n" +
"spring:\n" +
" profiles: con\n" +
" datasource:\n" +
" initialSize: 20\n" +
" namespace:\n" +
" url: www.baidu\n" +
"spring:";
String content = "#数据源连接数配置\n" +
"spring:\n" +
" profiles: con\n" +
" datasource:\n" +
" initialSize: 20\n" +
" minIdle: 50\n" +
" maxActive: 300\n";
String contentB = "#数据源连接数配置\n" +
"spring:\n" +
" profiles: con\n" +
" datasource:\n" +
" initialSize: 20\n" +
" namespace:\n" +
" url: www.baidu";
List<String> list = checkRepeatAttr(contentS);
System.out.println(list);
List<String> list1 = checkRepeatAttr(content, contentB);
System.out.println(list1);
List<String> list2 = checkRepeatAttr(contentB,content);
System.out.println(list2);
}