前言
我在遇到准备将一串符合yaml 的字符串进行解析,在搜索之后发现解析yaml 基本都是对文件进行解析。但自己字符串用 new Yaml().loadAs 无法解析,按道理也是支持字符串不应该不支持。想到自己字符串的换行可能不对,那么在java中如何才认为是一个换行呢?
BufferedWriter writer = new BufferedWriter(write);
writer.newLine() 这样一个方法,看了这个实现方式
String lineSeparator = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator"));
这个是一个换行符, 通过这个看到换行符实际就是一个\r\n 但是又给自己拼接出来不一样。
效果就是
自己拼接出来\r\n ,如果是通过上面反复获取到换行符那就是真的换行了。那么有了上面理解就有下面一篇对字符串解析的工具类
实践
package com.yin.common.util;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import sun.security.action.GetPropertyAction;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.AccessController;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
/**
* @author yin
* @since 2022/3/20 14:45
*/
public class YmlUtil {
private static Logger logger = LoggerFactory.getLogger(YmlUtil.class);
public static void main(String[] args) {
// Map<String, Object> targetMap = parseYamlFile("D:\\code\\plugin_demo\\web\\src\\main\\resources\\application.yml");
// for (Map.Entry<String, Object> entry : targetMap.entrySet()) {
// System.out.println(entry.getKey() + ":" + entry.getValue());
// }
StringBuilder ymlBuilder= new StringBuilder();
try( FileInputStream fileInputStream = new FileInputStream(new File("D:\\code\\plugin_demo\\web\\src\\main\\resources\\application.yml"));
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader=new BufferedReader(inputStreamReader)) {
String lineStr = "";
while ((lineStr = bufferedReader.readLine()) != null) {
ymlBuilder.append(lineStr).append("\\r\\n");
}
}catch (Exception e) {
logger.error("read fail", e);
}
System.out.println(ymlBuilder.toString());
Map<String, Object> targetMap = parseYamlString(ymlBuilder.toString());
for (Map.Entry<String, Object> entry : targetMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
/**
* 解析yaml 文件为map
* @param yamlFile 解析yaml
* @return 生成后的map
*/
public static Map<String,Object> parseYamlFile(String yamlFile){
File file = new File(yamlFile);
if (!file.exists()) {
return Collections.EMPTY_MAP;
}
LinkedHashMap<String, Object> sourceMap = null;
try (FileInputStream fileInputStream = new FileInputStream(file);) {
sourceMap= new Yaml().loadAs(fileInputStream
, LinkedHashMap.class);
} catch (Exception e) {
logger.error("parseYamlFile fail", e);
}
if (Objects.isNull(sourceMap)) {
return Collections.EMPTY_MAP;
}
LinkedHashMap<String, Object> targetMap = new LinkedHashMap<>(sourceMap.size());
fillAllPathMap(sourceMap, targetMap, "");
return targetMap;
}
/**
* 解析yaml 字符串为map
* @param yaml 解析yaml字符串
* @return 生成后的map
*/
public static Map<String,Object> parseYamlString(String yaml){
String lineSeparator = AccessController.doPrivileged(
new GetPropertyAction("line.separator"));
yaml = yaml.replace("\\r", "");
yaml = yaml.replace("\\n", lineSeparator);
LinkedHashMap<String, Object> sourceMap = null;
try {
sourceMap = new Yaml().loadAs(yaml, LinkedHashMap.class);
} catch (Exception e) {
logger.error("parseYamlString fail", e);
}
if (Objects.isNull(sourceMap)) {
return Collections.EMPTY_MAP;
}
LinkedHashMap<String, Object> targetMap = new LinkedHashMap<>(sourceMap.size());
fillAllPathMap(sourceMap, targetMap, "");
return targetMap;
}
/**
* 将sourceMap 中的多层结构改为一层
*/
private static void fillAllPathMap(Map<String,Object> sourceMap,Map<String,Object> targetMap,String prefix){
prefix = StringUtils.isEmpty(prefix) ? prefix : prefix + ".";
for (Map.Entry<String, Object> entry : sourceMap.entrySet()) {
Object value = entry.getValue();
if(Objects.nonNull(value) && (value instanceof Map)){
fillAllPathMap((Map) value, targetMap, prefix+entry.getKey());
}else{
targetMap.put(prefix+entry.getKey(), value);
}
}
}
}