170 lines
5.2 KiB
Java
170 lines
5.2 KiB
Java
|
|
package com.common.util;
|
|||
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|||
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|||
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
|
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|||
|
|
import com.fasterxml.jackson.core.JsonParser;
|
|||
|
|
import org.slf4j.Logger;
|
|||
|
|
import org.slf4j.LoggerFactory;
|
|||
|
|
|
|||
|
|
import java.util.*;
|
|||
|
|
import java.util.regex.Pattern;
|
|||
|
|
import java.util.regex.Matcher;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 嵌套JSON专门处理工具
|
|||
|
|
*/
|
|||
|
|
public class NestedJsonUtils {
|
|||
|
|
|
|||
|
|
private static final Logger logger = LoggerFactory.getLogger(NestedJsonUtils.class);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套值
|
|||
|
|
*/
|
|||
|
|
public static Object getNestedValue(Map<String, Object> data, String path) {
|
|||
|
|
return getNestedValue(data, path, null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套值(带默认值)
|
|||
|
|
*/
|
|||
|
|
@SuppressWarnings("unchecked")
|
|||
|
|
public static Object getNestedValue(Map<String, Object> data, String path, Object defaultValue) {
|
|||
|
|
if (data == null || path == null || path.trim().isEmpty()) {
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
String[] keys = path.split("\\.");
|
|||
|
|
Object current = data;
|
|||
|
|
|
|||
|
|
for (String key : keys) {
|
|||
|
|
if (current instanceof Map) {
|
|||
|
|
current = ((Map<String, Object>) current).get(key);
|
|||
|
|
} else {
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (current == null) {
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return current != null ? current : defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套字符串
|
|||
|
|
*/
|
|||
|
|
public static String getNestedString(Map<String, Object> data, String path) {
|
|||
|
|
return getNestedString(data, path, null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static String getNestedString(Map<String, Object> data, String path, String defaultValue) {
|
|||
|
|
Object value = getNestedValue(data, path, defaultValue);
|
|||
|
|
return value != null ? value.toString() : defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套整数
|
|||
|
|
*/
|
|||
|
|
public static Integer getNestedInteger(Map<String, Object> data, String path) {
|
|||
|
|
return getNestedInteger(data, path, null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static Integer getNestedInteger(Map<String, Object> data, String path, Integer defaultValue) {
|
|||
|
|
Object value = getNestedValue(data, path, defaultValue);
|
|||
|
|
|
|||
|
|
if (value instanceof Integer) {
|
|||
|
|
return (Integer) value;
|
|||
|
|
} else if (value instanceof String) {
|
|||
|
|
try {
|
|||
|
|
return Integer.parseInt((String) value);
|
|||
|
|
} catch (NumberFormatException e) {
|
|||
|
|
logger.warn("无法将值转换为整数: {}", value);
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
} else if (value instanceof Number) {
|
|||
|
|
return ((Number) value).intValue();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套Map
|
|||
|
|
*/
|
|||
|
|
@SuppressWarnings("unchecked")
|
|||
|
|
public static Map<String, Object> getNestedMap(Map<String, Object> data, String path) {
|
|||
|
|
Object value = getNestedValue(data, path, Collections.emptyMap());
|
|||
|
|
|
|||
|
|
if (value instanceof Map) {
|
|||
|
|
return (Map<String, Object>) value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Collections.emptyMap();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 安全地获取嵌套列表
|
|||
|
|
*/
|
|||
|
|
@SuppressWarnings("unchecked")
|
|||
|
|
public static List<Object> getNestedList(Map<String, Object> data, String path) {
|
|||
|
|
Object value = getNestedValue(data, path, Collections.emptyList());
|
|||
|
|
|
|||
|
|
if (value instanceof List) {
|
|||
|
|
return (List<Object>) value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Collections.emptyList();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 扁平化嵌套JSON
|
|||
|
|
*/
|
|||
|
|
public static LinkedHashMap<String, Object> flattenNestedJson(LinkedHashMap<String, Object> data) {
|
|||
|
|
return flattenNestedJson(data, null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 扁平化嵌套JSON(带前缀)
|
|||
|
|
*/
|
|||
|
|
@SuppressWarnings("unchecked")
|
|||
|
|
public static LinkedHashMap<String, Object> flattenNestedJson(Map<String, Object> data, String prefix) {
|
|||
|
|
LinkedHashMap<String, Object> flattened = new LinkedHashMap<>();
|
|||
|
|
String currentPrefix = prefix != null ? prefix + "." : "";
|
|||
|
|
|
|||
|
|
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
|||
|
|
String key = entry.getKey();
|
|||
|
|
Object value = entry.getValue();
|
|||
|
|
String fullKey = currentPrefix + key;
|
|||
|
|
|
|||
|
|
if (value instanceof Map) {
|
|||
|
|
flattened.putAll(flattenNestedJson((Map<String, Object>) value, fullKey));
|
|||
|
|
} else if (value instanceof List) {
|
|||
|
|
// 处理列表,可以按索引展开或保持为列表
|
|||
|
|
flattened.put(fullKey, value);
|
|||
|
|
} else {
|
|||
|
|
flattened.put(fullKey, value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return flattened;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证嵌套JSON结构
|
|||
|
|
*/
|
|||
|
|
public static boolean validateNestedStructure(Map<String, Object> data, String schema) {
|
|||
|
|
|
|||
|
|
// 项目中可以使用JSON Schema验证库
|
|||
|
|
try {
|
|||
|
|
// 这里可以实现自定义的结构验证逻辑
|
|||
|
|
return data != null && !data.isEmpty();
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
logger.error("嵌套结构验证失败", e);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|