import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.list.GrowthList;
import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.Yaml;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author kittlen
* @date 2024-04-01 14:56
* @description
*/
@Slf4j
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class YamlParserUtil {
/**
* YML file flows into single-layer map
* Change the order to Properties
*
* @param yamlContent
* @return
*/
public static Map<String, Object> yamlToFlattenedMap(String yamlContent) {
Yaml yaml = createYaml();
Map<String, Object> map = new HashMap<>();
for (Object object : yaml.loadAll(yamlContent)) {
if (object != null) {
map = asMap(object);
map = getFlattenedMap(map);
}
}
return map;
}
/**
* YML file flows into multiple nested maps
*
* @param yamlContent
* @return
*/
public static Map<String, Object> yamlToMultilayerMap(String yamlContent) {
Yaml yaml = createYaml();
Map<String, Object> result = new LinkedHashMap<>();
for (Object object : yaml.loadAll(yamlContent)) {
if (object != null) {
result.putAll(asMap(object));
}
}
return result;
}
/**
* Convert maps to yml multiple times
*
* @param map
* @return
*/
public static String multilayerMapToYaml(Map<String, Object> map) {
Yaml yaml = createYaml();
return yaml.dumpAsMap(map);
}
/**
* Convert single-layer map to yml
*
* @param map
* @return
*/
public static String flattenedMapToYaml(Map<String, Object> map) {
Yaml yaml = createYaml();
return yaml.dumpAsMap(flattenedMapToMultilayerMap(map));
}
/**
* Single-layer map conversion multi-layer map
*
* @param map
* @return
*/
private static Map<String, Object> flattenedMapToMultilayerMap(Map<String, Object> map) {
return getMultilayerMap(map);
}
private static Yaml createYaml() {
return new Yaml();
}
@SuppressWarnings("unchecked")
private static Map<String, Object> asMap(Object object) {
Map<String, Object> result = new LinkedHashMap<>();
if (!(object instanceof Map)) {
result.put("document", object);
return result;
}
Map<Object, Object> map = (Map<Object, Object>) object;
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object value = entry.getValue();
if (value instanceof Map) {
value = asMap(value);
}
Object key = entry.getKey();
if (key instanceof CharSequence) {
result.put(key.toString(), value);
} else {
result.put("[" + key.toString() + "]", value);
}
}
return result;
}
private static Map<String, Object> getFlattenedMap(Map<String, Object> source) {
Map<String, Object> result = new LinkedHashMap<>();
buildFlattenedMap(result, source, null);
return result;
}
private static void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {
for (Map.Entry<String, Object> entry : source.entrySet()) {
String key = entry.getKey();
if (!StringUtils.isBlank(path)) {
if (key.startsWith("[")) {
key = path + key;
} else {
key = path + '.' + key;
}
}
Object value = entry.getValue();
if (value instanceof String) {
result.put(key, value);
} else if (value instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) value;
buildFlattenedMap(result, map, key);
} else if (value instanceof Collection) {
@SuppressWarnings("unchecked")
Collection<Object> collection = (Collection<Object>) value;
int count = 0;
for (Object object : collection) {
buildFlattenedMap(result, Collections.singletonMap("[" + (count++) + "]", object), key);
}
} else {
result.put(key, (value != null ? value.toString() : ""));
}
}
}
private static Map<String, Object> getMultilayerMap(Map<String, Object> source) {
Map<String, Object> rootResult = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : source.entrySet()) {
String key = entry.getKey();
buildMultilayerMap(rootResult, key, entry.getValue());
}
return rootResult;
}
@SuppressWarnings("unchecked")
private static void buildMultilayerMap(Map<String, Object> parent, String path, Object value) {
String[] keys = StringUtils.split(path, ".");
String key = keys[0];
if (key.endsWith("]")) {
String listKey = key.substring(0, key.indexOf("["));
String listPath = path.substring(key.indexOf("["));
List<Object> chlid = bulidChlidList(parent, listKey);
buildMultilayerList(chlid, listPath, value);
} else {
if (keys.length == 1) {
parent.put(key, stringToObj(value.toString()));
} else {
String newpath = path.substring(path.indexOf(".") + 1);
Map<String, Object> chlid = bulidChlidMap(parent, key);
buildMultilayerMap(chlid, newpath, value);
}
}
}
@SuppressWarnings("unchecked")
private static void buildMultilayerList(List<Object> parent, String path, Object value) {
String[] keys = StringUtils.split(path, ".");
String key = keys[0];
int index = Integer.parseInt(key.replace("[", "").replace("]", ""));
if (keys.length == 1) {
parent.add(index, stringToObj(value.toString()));
} else {
String newpath = path.substring(path.indexOf(".") + 1);
Map<String, Object> chlid = bulidChlidMap(parent, index);
buildMultilayerMap(chlid, newpath, value);
}
}
@SuppressWarnings("unchecked")
private static Map<String, Object> bulidChlidMap(Map<String, Object> parent, String key) {
if (parent.containsKey(key)) {
return (Map<String, Object>) parent.get(key);
} else {
Map<String, Object> chlid = new LinkedHashMap<>(16);
parent.put(key, chlid);
return chlid;
}
}
@SuppressWarnings("unchecked")
private static Map<String, Object> bulidChlidMap(List<Object> parent, int index) {
Map<String, Object> chlid = null;
try {
Object obj = parent.get(index);
if (null != obj) {
chlid = (Map<String, Object>) obj;
}
} catch (Exception e) {
log.warn("get list error");
}
if (null == chlid) {
chlid = new LinkedHashMap<>(16);
parent.add(index, chlid);
}
return chlid;
}
@SuppressWarnings("unchecked")
private static List<Object> bulidChlidList(Map<String, Object> parent, String key) {
if (parent.containsKey(key)) {
return (List<Object>) parent.get(key);
} else {
List<Object> chlid = new GrowthList(16);
parent.put(key, chlid);
return chlid;
}
}
private static Object stringToObj(String obj) {
Object result;
if (obj.equals("true") || obj.equals("false")) {
result = Boolean.valueOf(obj);
} else if (isBigDecimal(obj)) {
if (obj.indexOf(".") == -1) {
result = Long.valueOf(obj);
} else {
result = Double.valueOf(obj);
}
} else {
result = obj;
}
return result;
}
public static boolean isBigDecimal(CharSequence self) {
try {
new BigDecimal(self.toString().trim());
return true;
} catch (NumberFormatException var2) {
return false;
}
}
public static void main(String[] args) {
String content = "feign:\n" +
" hystrix:\n" +
" enabled: true\n" +
" client:\n" +
" config:\n" +
" default:\n" +
" connectTimeout: 10000\n" +
" readTimeout: 60000\n" +
"management:\n" +
" health:\n" +
" db:\n" +
" enabled: false\n" +
" endpoints:\n" +
" web:\n" +
" base-path: /health";
Map<String, Object> a = YamlParserUtil.yamlToFlattenedMap(content);
System.out.println(a);
Map<String, Object> b = YamlParserUtil.yamlToMultilayerMap(content);
System.out.println(b);
String c = YamlParserUtil.multilayerMapToYaml(b);
System.out.println(c);
String d = YamlParserUtil.flattenedMapToYaml(a);
System.out.println(d);
}
}