You've already forked FrameTour-BE
526 lines
17 KiB
Java
526 lines
17 KiB
Java
package com.ycwl.basic.utils;
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
import com.fasterxml.jackson.databind.type.CollectionType;
|
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
|
|
|
import java.io.IOException;
|
|
import java.text.SimpleDateFormat;
|
|
import java.time.ZoneId;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.TimeZone;
|
|
|
|
/**
|
|
* Jackson JSON工具类
|
|
* 提供简单易用的JSON序列化和反序列化功能
|
|
*/
|
|
public class JacksonUtil {
|
|
|
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
|
static {
|
|
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
|
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
|
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
|
objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));
|
|
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
|
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
|
|
objectMapper.configure(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, true);
|
|
objectMapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, false);
|
|
}
|
|
|
|
/**
|
|
* 对象转JSON字符串
|
|
* @param obj 要转换的对象
|
|
* @return JSON字符串
|
|
*/
|
|
public static String toJson(Object obj) {
|
|
try {
|
|
return objectMapper.writeValueAsString(obj);
|
|
} catch (JsonProcessingException e) {
|
|
throw new RuntimeException("对象转JSON失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSON字符串转对象
|
|
* @param json JSON字符串
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T fromJson(String json, Class<T> clazz) {
|
|
try {
|
|
return objectMapper.readValue(json, clazz);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("JSON转对象失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSON字符串转对象(支持复杂类型)
|
|
* @param json JSON字符串
|
|
* @param typeReference 类型引用
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T fromJson(String json, TypeReference<T> typeReference) {
|
|
try {
|
|
return objectMapper.readValue(json, typeReference);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("JSON转对象失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSON字符串转List
|
|
* @param json JSON字符串
|
|
* @param elementClass 列表元素类型
|
|
* @param <T> 泛型类型
|
|
* @return List对象
|
|
*/
|
|
public static <T> List<T> fromJsonToList(String json, Class<T> elementClass) {
|
|
try {
|
|
TypeFactory typeFactory = objectMapper.getTypeFactory();
|
|
CollectionType listType = typeFactory.constructCollectionType(List.class, elementClass);
|
|
return objectMapper.readValue(json, listType);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("JSON转List失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSON字符串转Map
|
|
* @param json JSON字符串
|
|
* @return Map对象
|
|
*/
|
|
public static Map<String, Object> fromJsonToMap(String json) {
|
|
try {
|
|
return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("JSON转Map失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取JSON节点
|
|
* @param json JSON字符串
|
|
* @return JsonNode对象
|
|
*/
|
|
public static JsonNode getJsonNode(String json) {
|
|
try {
|
|
return objectMapper.readTree(json);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("解析JSON失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取字符串值
|
|
* @param json JSON字符串
|
|
* @param path 路径(支持嵌套,如:"user.name")
|
|
* @return 字符串值
|
|
*/
|
|
public static String getString(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isNull() ? node.asText() : null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取整数值
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @return 整数值
|
|
*/
|
|
public static Integer getInt(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isNull() ? node.asInt() : null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取长整数值
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @return 长整数值
|
|
*/
|
|
public static Long getLong(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isNull() ? node.asLong() : null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取双精度浮点数值
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @return 双精度浮点数值
|
|
*/
|
|
public static Double getDouble(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isNull() ? node.asDouble() : null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取布尔值
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @return 布尔值
|
|
*/
|
|
public static Boolean getBoolean(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isNull() ? node.asBoolean() : null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取对象
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return 对象
|
|
*/
|
|
public static <T> T getObject(String json, String path, Class<T> clazz) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
if (node != null && !node.isNull()) {
|
|
try {
|
|
return objectMapper.treeToValue(node, clazz);
|
|
} catch (JsonProcessingException e) {
|
|
throw new RuntimeException("JSON节点转对象失败", e);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 从JSON中获取数组
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @param elementClass 数组元素类型
|
|
* @param <T> 泛型类型
|
|
* @return List对象
|
|
*/
|
|
public static <T> List<T> getArray(String json, String path, Class<T> elementClass) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
if (node != null && node.isArray()) {
|
|
try {
|
|
TypeFactory typeFactory = objectMapper.getTypeFactory();
|
|
CollectionType listType = typeFactory.constructCollectionType(List.class, elementClass);
|
|
return objectMapper.treeToValue(node, listType);
|
|
} catch (JsonProcessingException e) {
|
|
throw new RuntimeException("JSON节点转数组失败", e);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 检查JSON中是否存在指定路径
|
|
* @param json JSON字符串
|
|
* @param path 路径
|
|
* @return 是否存在
|
|
*/
|
|
public static boolean hasPath(String json, String path) {
|
|
JsonNode node = getValueByPath(json, path);
|
|
return node != null && !node.isMissingNode();
|
|
}
|
|
|
|
/**
|
|
* 根据路径获取JSON节点值
|
|
* @param json JSON字符串
|
|
* @param path 路径(支持嵌套,如:"user.name"或"users[0].name")
|
|
* @return JsonNode对象
|
|
*/
|
|
private static JsonNode getValueByPath(String json, String path) {
|
|
try {
|
|
JsonNode rootNode = objectMapper.readTree(json);
|
|
String[] pathParts = path.split("\\.");
|
|
JsonNode currentNode = rootNode;
|
|
|
|
for (String part : pathParts) {
|
|
if (currentNode == null || currentNode.isMissingNode()) {
|
|
return null;
|
|
}
|
|
|
|
// 处理数组索引,如:users[0]
|
|
if (part.contains("[") && part.contains("]")) {
|
|
String fieldName = part.substring(0, part.indexOf("["));
|
|
String indexStr = part.substring(part.indexOf("[") + 1, part.indexOf("]"));
|
|
int index = Integer.parseInt(indexStr);
|
|
|
|
currentNode = currentNode.get(fieldName);
|
|
if (currentNode != null && currentNode.isArray() && index < currentNode.size()) {
|
|
currentNode = currentNode.get(index);
|
|
} else {
|
|
return null;
|
|
}
|
|
} else {
|
|
currentNode = currentNode.get(part);
|
|
}
|
|
}
|
|
|
|
return currentNode;
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("获取JSON路径值失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 美化JSON字符串(格式化输出)
|
|
* @param json JSON字符串
|
|
* @return 格式化后的JSON字符串
|
|
*/
|
|
public static String prettyPrint(String json) {
|
|
try {
|
|
JsonNode node = objectMapper.readTree(json);
|
|
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("JSON格式化失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取ObjectMapper实例(用于高级用法)
|
|
* @return ObjectMapper实例
|
|
*/
|
|
public static ObjectMapper getObjectMapper() {
|
|
return objectMapper;
|
|
}
|
|
|
|
// ==== FastJSON 兼容性方法 ====
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSON.toJSONString() 方法
|
|
* @param obj 要转换的对象
|
|
* @return JSON字符串
|
|
*/
|
|
public static String toJSONString(Object obj) {
|
|
return toJson(obj);
|
|
}
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSON.parseObject() 方法
|
|
* @param json JSON字符串
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T parseObject(String json, Class<T> clazz) {
|
|
return fromJson(json, clazz);
|
|
}
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSON.parseArray() 方法
|
|
* @param json JSON字符串
|
|
* @param clazz 数组元素类型
|
|
* @param <T> 泛型类型
|
|
* @return List对象
|
|
*/
|
|
public static <T> List<T> parseArray(String json, Class<T> clazz) {
|
|
return fromJsonToList(json, clazz);
|
|
}
|
|
|
|
/**
|
|
* 带TypeReference的parseObject方法,支持复杂泛型
|
|
* @param json JSON字符串
|
|
* @param typeReference 类型引用
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T parseObject(String json, TypeReference<T> typeReference) {
|
|
return fromJson(json, typeReference);
|
|
}
|
|
|
|
/**
|
|
* 将Map或其他对象转换为指定类型,兼容fastjson的toJavaObject方法
|
|
* @param obj 源对象
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T toJavaObject(Object obj, Class<T> clazz) {
|
|
if (obj == null) {
|
|
return null;
|
|
}
|
|
try {
|
|
// 如果对象已经是目标类型,直接返回
|
|
if (clazz.isInstance(obj)) {
|
|
return clazz.cast(obj);
|
|
}
|
|
// 先转为JSON字符串,再转为目标对象
|
|
String json = toJson(obj);
|
|
return fromJson(json, clazz);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("对象转换失败", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSONObject.parseObject() 方法
|
|
* @param json JSON字符串
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return 转换后的对象
|
|
*/
|
|
public static <T> T parseObjectCompat(String json, Class<T> clazz) {
|
|
return fromJson(json, clazz);
|
|
}
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSONObject.toJSONString() 方法
|
|
* @param obj 要转换的对象
|
|
* @return JSON字符串
|
|
*/
|
|
public static String toJSONStringCompat(Object obj) {
|
|
return toJson(obj);
|
|
}
|
|
|
|
/**
|
|
* 兼容 FastJSON 的 JSONObject.parseArray() 方法
|
|
* @param json JSON字符串
|
|
* @param clazz 数组元素类型
|
|
* @param <T> 泛型类型
|
|
* @return List对象
|
|
*/
|
|
public static <T> List<T> parseArrayCompat(String json, Class<T> clazz) {
|
|
return fromJsonToList(json, clazz);
|
|
}
|
|
|
|
/**
|
|
* 简单的JSON对象包装类,兼容部分JSONObject的用法
|
|
*/
|
|
public static class JSONObjectCompat {
|
|
private final JsonNode node;
|
|
|
|
private JSONObjectCompat(JsonNode node) {
|
|
this.node = node;
|
|
}
|
|
|
|
/**
|
|
* 解析JSON字符串为JSONObjectCompat
|
|
* @param json JSON字符串
|
|
* @return JSONObjectCompat对象
|
|
*/
|
|
public static JSONObjectCompat parseObject(String json) {
|
|
return new JSONObjectCompat(getJsonNode(json));
|
|
}
|
|
|
|
/**
|
|
* 获取JSON数组
|
|
* @param key 键名
|
|
* @return JSON数组的List表示
|
|
*/
|
|
public List<JSONObjectCompat> getJSONArray(String key) {
|
|
JsonNode arrayNode = node.get(key);
|
|
if (arrayNode != null && arrayNode.isArray()) {
|
|
List<JSONObjectCompat> result = new java.util.ArrayList<>();
|
|
for (JsonNode item : arrayNode) {
|
|
result.add(new JSONObjectCompat(item));
|
|
}
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 获取JSON对象
|
|
* @param index 索引
|
|
* @return JSONObjectCompat对象
|
|
*/
|
|
public JSONObjectCompat getJSONObject(int index) {
|
|
if (node.isArray() && index < node.size()) {
|
|
return new JSONObjectCompat(node.get(index));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 获取字符串值
|
|
* @param key 键名
|
|
* @return 字符串值
|
|
*/
|
|
public String getString(String key) {
|
|
JsonNode valueNode = node.get(key);
|
|
return valueNode != null && !valueNode.isNull() ? valueNode.asText() : null;
|
|
}
|
|
|
|
/**
|
|
* 获取整数值
|
|
* @param key 键名
|
|
* @return 整数值
|
|
*/
|
|
public Integer getInteger(String key) {
|
|
JsonNode valueNode = node.get(key);
|
|
return valueNode != null && !valueNode.isNull() ? valueNode.asInt() : null;
|
|
}
|
|
|
|
/**
|
|
* 获取长整数值
|
|
* @param key 键名
|
|
* @return 长整数值
|
|
*/
|
|
public Long getLong(String key) {
|
|
JsonNode valueNode = node.get(key);
|
|
return valueNode != null && !valueNode.isNull() ? valueNode.asLong() : null;
|
|
}
|
|
|
|
/**
|
|
* 获取双精度浮点数值
|
|
* @param key 键名
|
|
* @return 双精度浮点数值
|
|
*/
|
|
public Double getDouble(String key) {
|
|
JsonNode valueNode = node.get(key);
|
|
return valueNode != null && !valueNode.isNull() ? valueNode.asDouble() : null;
|
|
}
|
|
|
|
/**
|
|
* 获取布尔值
|
|
* @param key 键名
|
|
* @return 布尔值
|
|
*/
|
|
public Boolean getBoolean(String key) {
|
|
JsonNode valueNode = node.get(key);
|
|
return valueNode != null && !valueNode.isNull() ? valueNode.asBoolean() : null;
|
|
}
|
|
|
|
/**
|
|
* 获取键集合
|
|
* @return 键的Set集合
|
|
*/
|
|
public java.util.Set<String> keySet() {
|
|
if (node.isObject()) {
|
|
java.util.Set<String> keys = new java.util.HashSet<>();
|
|
node.fieldNames().forEachRemaining(keys::add);
|
|
return keys;
|
|
}
|
|
return java.util.Collections.emptySet();
|
|
}
|
|
|
|
/**
|
|
* 检查是否包含指定键
|
|
* @param key 键名
|
|
* @return 是否包含
|
|
*/
|
|
public boolean containsKey(String key) {
|
|
return node.has(key);
|
|
}
|
|
|
|
/**
|
|
* 转换为Java对象
|
|
* @param clazz 目标类型
|
|
* @param <T> 泛型类型
|
|
* @return Java对象
|
|
*/
|
|
public <T> T toJavaObject(Class<T> clazz) {
|
|
try {
|
|
return objectMapper.treeToValue(node, clazz);
|
|
} catch (JsonProcessingException e) {
|
|
throw new RuntimeException("JSON节点转对象失败", e);
|
|
}
|
|
}
|
|
}
|
|
} |