在现代软件开发中,JSON(JavaScript Object Notation)已成为数据交换的“通用语言”——从前后端接口通信到微服务数据交互,从配置文件解析到日志格式化,几乎所有场景都离不开JSON的处理。然而,原生JSON框架(如FastJSON、Jackson)的API往往需要大量重复代码,且空指针、格式异常等问题频发。
本文分享的JsonUtil
工具类,基于FastJSON、Jackson等主流框架封装,整合了18+高频功能,从基础的格式转换到复杂的JSON合并,从安全的字段提取到批量内容替换,全方位覆盖开发需求。下文将从核心能力、源码解析、实战场景、优势对比等维度展开,帮助开发者彻底掌握JSON高效处理技巧。
一、JsonUtil核心能力全景:从基础到复杂场景
JsonUtil
的设计遵循“业务驱动”原则——所有方法均源自实际开发中的高频需求。其核心能力可分为六大类,覆盖JSON处理的全生命周期:
1. JSON合并:多源数据整合的终极方案
在微服务架构中,一个业务数据往往需要从多个接口获取(如商品详情需合并基础信息、库存、评价等接口数据);在前端开发中,组件数据可能来自多个数据源。JsonUtil
的合并能力正是为解决这类问题设计,支持JSONObject
和JSONArray
两种合并场景。
- JSONObject合并(
jsonMerge
):以目标JSON为基础,用源JSON的字段覆盖或递归合并(支持嵌套结构)。 - JSONArray合并(
jsonArrayMerge
):将两个数组元素合并为新数组,支持嵌套JSON的深拷贝。
2. 格式转换:对象与JSON的无缝衔接
对象与JSON的转换是日常开发中最频繁的操作之一。JsonUtil
封装了多种转换逻辑,支持“对象→JSON字符串”“JSON字符串→对象”“集合→JSONArray”等全场景。
- 基础转换:
fromJsonStringToT
(JSON字符串→对象)、objectToJson
(对象→JSONObject)。 - 集合转换:
jsonToList
(JSON→List)、listToJsonArray
(List→JSONArray)。 - Map转换:
jsonToMap
(JSON→Map)、jsonToList
(JSON→List
3. 安全提取:从JSON中获取字段的“防坑”实践
直接从JSON中提取字段时,若字段不存在或类型不匹配,极易抛出NullPointerException
或类型转换异常。JsonUtil
的提取方法通过“默认值兜底”机制,彻底解决这类问题。
- 基础类型提取:
getString
(默认空串)、getInt
(默认0)、getBoolean
(默认false)。 - 复杂类型提取:
getJsonObject
(默认null)、getJsonArray
(默认null)。
4. 校验与修改:JSON格式校验与内容批量处理
在接收外部数据(如用户输入、第三方接口返回)时,需先校验JSON格式合法性;在日志处理、数据清洗场景中,需批量修改JSON中的特定内容。JsonUtil
提供了完整的校验与修改能力。
- 格式校验:
isJsonStr
(FastJSON校验)、isGsonStr
(Gson校验)。 - 内容修改:
replaceStringInJson
(递归替换JSON中的字符串)。
5. 自定义转换:按需过滤字段的轻量方案
有时需要将对象转换为JSON,但仅保留部分字段(如接口返回时隐藏敏感字段)。JsonUtil
的自定义转换方法通过反射实现字段过滤,无需手动构建Map。
listToStringIncludeArrays
(List对象→仅含指定字段的JSON)。objectToStringIncludeArrays
(单个对象→仅含指定字段的JSON)。
6. 深拷贝:避免引用传递的“独立副本”生成
JSON对象默认是引用传递,修改拷贝对象可能影响原对象。JsonUtil
的合并、转换方法中内置深拷贝逻辑,通过序列化实现对象的完全独立。
二、核心方法深度解析:从源码到原理
1. JSON合并(jsonMerge
):递归逻辑与边界处理
业务场景:电商商品详情页需要合并“基础信息接口”(含名称、价格)和“库存接口”(含库存数量、仓库位置)的返回数据,且需保留双方的非重复字段。
方法作用:用source
(源JSON)的字段覆盖target
(目标JSON)的同名字段,若字段是嵌套JSONObject
则递归合并,若为JSONArray
则按索引合并元素。
源码核心逻辑:
public static JSONObject jsonMerge(JSONObject source, JSONObject target) {
if (source == null) return target;
if (target == null) return source;
try {
for (String key : source.keySet()) {
Object value = source.get(key);
// 1. 目标JSON不含该key:直接添加
if (!target.containsKey(key)) {
target.put(key, value);
continue;
}
// 2. 字段是JSONObject:递归合并
if (value instanceof JSONObject) {
JSONObject mergedValue = jsonMerge((JSONObject) value, target.getJSONObject(key));
target.put(key, mergedValue);
continue;
}
// 3. 字段是JSONArray:按索引合并元素(需长度一致)
if (value instanceof JSONArray) {
JSONArray sourceArray = (JSONArray) value;
JSONArray targetArray = target.getJSONArray(key);
if (sourceArray.size() != targetArray.size()) {
throw new IllegalArgumentException("数组长度不一致:" + key);
}
for (int i = 0; i < sourceArray.size(); i++) {
Object sourceItem = sourceArray.get(i);
Object targetItem = targetArray.get(i);
// 仅合并数组中的JSONObject元素
if (sourceItem instanceof JSONObject && targetItem instanceof JSONObject) {
targetArray.set(i, jsonMerge((JSONObject) sourceItem, (JSONObject) targetItem));
}
}
continue;
}
// 4. 其他类型(字符串、数字等):直接覆盖
target.put(key, value);
}
} catch (Exception e) {
logger.error("JSON合并失败", e);
throw new RuntimeException("合并失败", e);
}
return target;
}
关键设计:
- 递归处理嵌套JSON:若字段是
JSONObject
,通过自身递归实现深层合并(如{"a":{"b":1}}
与{"a":{"c":2}}
合并为{"a":{"b":1,"c":2}}
)。 - 数组长度校验:避免因数组长度不一致导致的索引越界(如合并商品图片数组时,确保双方图片数量相同)。
- 异常兜底:合并失败时记录日志并抛出运行时异常,避免静默失败(如生产环境中数据合并错误需及时报警)。
2. 安全提取(getString
、getInt
):空值处理的最佳实践
业务痛点:从接口返回的JSON中获取“用户手机号”时,若接口未返回该字段,直接调用json.getString("phone")
会返回null
,后续调用phone.length()
将抛出空指针异常。
方法作用:获取字段值时,若字段不存在或为null
,返回预设默认值(字符串返回空串,整数返回0)。
源码解析:
public static String getString(JSONObject jsonObject, String key) {
// 若jsonObject为null,或字段值为null,返回空串
return Objects.nonNull(jsonObject) && Objects.nonNull(jsonObject.getString(key))
? jsonObject.getString(key)
: "";
}
public static int getInt(JSONObject jsonObject, String key) {
// 若jsonObject为null,或字段值为null,返回0
return Objects.nonNull(jsonObject) && Objects.nonNull(jsonObject.getInteger(key))
? jsonObject.getInteger(key)
: 0;
}
使用示例:
JSONObject userJson = JSON.parseObject("{\"name\":\"张三\"}");
// 安全获取存在的字段
String name = JsonUtil.getString(userJson, "name"); // "张三"
// 安全获取不存在的字段(返回空串,避免null)
String phone = JsonUtil.getString(userJson, "phone"); // ""
// 安全获取整数(不存在返回0,避免空指针)
int age = JsonUtil.getInt(userJson, "age"); // 0
3. 自定义转换(objectToStringIncludeArrays
):反射过滤字段
业务场景:用户列表接口需要返回用户信息,但仅保留“id”“name”字段,隐藏“password”“idCard”等敏感信息。
方法作用:通过反射获取对象的指定字段值,生成仅含这些字段的JSON字符串,无需手动创建Map。
源码核心逻辑:
// 核心工具方法:将对象转换为仅含指定字段的Map
private static Map<String, Object> objectToMapIncludeArrays(Object object, String[] arrays) {
Map<String, Object> result = new HashMap<>();
for (String fieldName : arrays) {
if (object instanceof Map) {
// 若对象是Map,直接取key对应的值
result.put(fieldName, ((Map<?, ?>) object).get(fieldName));
} else {
// 若对象是普通实体,通过反射获取字段值
try {
Object value = getFieldValueByObject(object, fieldName);
result.put(fieldName, value);
} catch (Exception e) {
logger.error("反射获取字段值失败", e);
}
}
}
return result;
}
// 反射获取字段值(支持父类字段)
private static Object getFieldValueByObject(Object object, String targetFieldName) throws Exception {
Class<?> objClass = object.getClass();
// 先查当前类字段
for (Field field : objClass.getDeclaredFields()) {
if (field.getName().equals(targetFieldName)) {
field.setAccessible(true); // 突破私有字段访问限制
return field.get(object);
}
}
// 再查父类字段(如User类继承自BaseEntity,需获取父类的id字段)
Class<?> superClass = objClass.getSuperclass();
if (superClass != null) {
for (Field field : superClass.getDeclaredFields()) {
if (field.getName().equals(targetFieldName)) {
field.setAccessible(true);
return field.get(object);
}
}
}
return null;
}
使用示例:
// 定义用户类(含敏感字段)
class User {
private Long id;
private String name;
private String password; // 敏感字段,需隐藏
// getter/setter
}
// 创建用户对象
User user = new User();
user.setId(1L);
user.setName("张三");
user.setPassword("123456");
// 仅保留"id"和"name"字段,生成JSON
String userJson = JsonUtil.objectToStringIncludeArrays(user, new String[]{"id", "name"});
// 输出:{"id":1,"name":"张三"}(无password字段)
4. 内容替换(replaceStringInJson
):递归遍历JSON
业务场景:日志系统中,所有JSON格式的日志需将“旧域名(old.com)”替换为“新域名(new.com)”,包括嵌套在深层的字段(如{"ext":{"url":"http://old.com/path"}}
)。
方法作用:递归遍历JSON的所有字段(包括嵌套JSONObject
和JSONArray
),批量替换字符串内容。
源码核心逻辑:
// 入口方法:JSON字符串替换
public static String replaceStringInJson(String jsonString, String oldString, String newString) {
try {
JSONObject json = JSON.parseObject(jsonString);
replaceStringInJson(json, oldString, newString); // 调用递归方法
return json.toString();
} catch (JSONException e) {
logger.error("JSON替换失败", e);
return jsonString; // 失败时返回原始字符串,避免业务中断
}
}
// 递归方法:处理JSONObject和JSONArray
private static void replaceStringInJson(Object object, String oldString, String newString) {
if (object instanceof JSONObject) {
// 处理JSONObject:遍历所有key
JSONObject json = (JSONObject) object;
for (String key : json.keySet()) {
Object value = json.get(key);
if (value instanceof String) {
// 字符串类型:直接替换
String newValue = ((String) value).replaceAll(oldString, newString);
json.put(key, newValue);
} else {
// 非字符串:递归处理(可能是JSONObject/JSONArray)
replaceStringInJson(value, oldString, newString);
}
}
} else if (object instanceof JSONArray) {
// 处理JSONArray:遍历所有元素
JSONArray jsonArray = (JSONArray) object;
for (Object item : jsonArray) {
replaceStringInJson(item, oldString, newString); // 递归处理元素
}
}
}
使用示例:
String jsonStr = "{" +
"\"name\":\"旧文本示例\"," +
"\"ext\":{\"desc\":\"旧文本需要替换\"}," +
"\"tags\":[{\"label\":\"旧标签\"}]" +
"}";
// 将所有"旧"替换为"新"
String newJson = JsonUtil.replaceStringInJson(jsonStr, "旧", "新");
// 输出结果:
// {
// "name":"新文本示例",
// "ext":{"desc":"新文本需要替换"},
// "tags":[{"label":"新标签"}]
// }
三、实战场景:从业务需求到工具应用
场景1:微服务数据合并(jsonMerge
)
需求:电商商品详情页需整合3个接口数据:
- 基础接口:
{"id":1,"name":"手机","price":3999}
- 库存接口:
{"id":1,"stock":100,"warehouse":"北京仓"}
- 促销接口:
{"id":1,"discount":0.9,"activity":"限时折扣"}
实现步骤:
- 调用3个接口,获取返回的JSON数据;
- 以基础接口数据为
target
,依次合并库存、促销接口数据; - 返回合并后的完整商品信息。
代码示例:
// 模拟接口返回数据
JSONObject baseJson = JSON.parseObject("{\"id\":1,\"name\":\"手机\",\"price\":3999}");
JSONObject stockJson = JSON.parseObject("{\"id\":1,\"stock\":100,\"warehouse\":\"北京仓\"}");
JSONObject promotionJson = JSON.parseObject("{\"id\":1,\"discount\":0.9,\"activity\":\"限时折扣\"}");
// 合并数据:基础信息 → 合并库存 → 合并促销
JSONObject productJson = JsonUtil.jsonMerge(stockJson, baseJson);
productJson = JsonUtil.jsonMerge(promotionJson, productJson);
// 输出合并结果
// {
// "id":1,
// "name":"手机",
// "price":3999,
// "stock":100,
// "warehouse":"北京仓",
// "discount":0.9,
// "activity":"限时折扣"
// }
场景2:敏感字段过滤(listToStringIncludeArrays
)
需求:用户管理接口返回用户列表时,仅展示“id”“username”“role”字段,隐藏“password”“email”等敏感信息。
实现步骤:
- 从数据库查询用户列表(含所有字段);
- 使用
listToStringIncludeArrays
过滤字段,生成仅含指定字段的JSON; - 返回过滤后的JSON给前端。
代码示例:
// 模拟数据库查询结果
List<User> userList = new ArrayList<>();
userList.add(new User(1L, "zhangsan", "123456", "zhangsan@old.com", "admin"));
userList.add(new User(2L, "lisi", "654321", "lisi@old.com", "user"));
// 仅保留"id"、"username"、"role"字段
String userListJson = JsonUtil.listToStringIncludeArrays(userList, new String[]{"id", "username", "role"});
// 输出:
// [
// {"id":1,"username":"zhangsan","role":"admin"},
// {"id":2,"username":"lisi","role":"user"}
// ]
场景3:日志内容替换(replaceStringInJson
)
需求:所有JSON格式的操作日志中,需将用户手机号(如“13800138000”)中间4位替换为“****”,保护隐私。
实现步骤:
- 日志生成时,获取原始JSON日志字符串;
- 使用正则表达式匹配手机号,调用
replaceStringInJson
替换; - 输出处理后的日志。
代码示例:
// 原始日志(含手机号)
String logJson = "{" +
"\"operate\":\"login\"," +
"\"user\":{\"name\":\"张三\",\"phone\":\"13800138000\"}," +
"\"ext\":{\"device\":\"phone\",\"contact\":\"13900139000\"}" +
"}";
// 替换手机号中间4位(使用正则:(\d{3})\d{4}(\d{4}) → $1****$2)
String maskedLog = JsonUtil.replaceStringInJson(logJson, "(\\d{3})\\d{4}(\\d{4})", "$1****$2");
// 输出结果:
// {
// "operate":"login",
// "user":{"name":"张三","phone":"138****8000"},
// "ext":{"device":"phone","contact":"139****9000"}
// }
四、JsonUtil的优势:对比原生框架
处理场景 | 原生FastJSON/Jackson | JsonUtil工具类 |
---|---|---|
JSON合并 | 需要手动遍历字段,递归处理嵌套结构(约20行代码) | 一行代码调用jsonMerge ,自动处理嵌套 |
安全提取字段 | 需手动判断null (如json!=null?json.getString(key):"" ) | 直接调用getString ,内置空值处理 |
字段过滤 | 需手动创建Map,逐个put字段(约10行代码) | 一行代码指定字段,反射自动提取 |
内容替换 | 需手动递归遍历JSON,处理数组和嵌套对象 | 一行代码调用replaceStringInJson ,自动递归 |
异常处理 | 需手动捕获JSONException ,编写日志逻辑 | 内置异常处理,自动记录日志并兜底 |
五、扩展建议与注意事项
1. 扩展方向
- 支持JSONPath:添加
getByJsonPath
方法(如通过$.user.name
直接获取嵌套字段),提升复杂JSON的提取效率。 - 超大JSON处理:针对100MB+的JSON,改用流式解析(如Jackson的
JsonParser
),避免一次性加载到内存导致OOM。 - 类型转换增强:支持日期格式自定义(如
yyyy-MM-dd
),解决JSON中日期字段默认格式(时间戳)不直观的问题。
2. 注意事项
- 序列化依赖:深拷贝和合并功能依赖对象可序列化(若处理自定义对象,需确保其实现
Serializable
接口)。 - 数组长度限制:
jsonMerge
方法要求合并的JSONArray
长度一致,若需支持不同长度,可修改源码去除校验(需注意索引越界风险)。 - 性能考量:反射和递归操作(如
objectToStringIncludeArrays
、replaceStringInJson
)对超大对象有性能损耗,高频场景建议缓存结果。
六、源代码
代码示例:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
/**
* @ClassName: JsonUtil
* @Description: JSON操作工具类
* @Version 1.0
*/
public class JsonUtil {
private static final Logger logger = LogManager.getLogger(JsonUtil.class);
/**
* 合并JSON对象,用source覆盖target,返回覆盖后的JSON对象
*/
public static JSONObject jsonMerge(JSONObject source, JSONObject target) {
// 参数校验
if (source == null) {
logger.error("参数source为空,返回target数据!");
return target;
}
if (target == null) {
logger.error("参数target为空,返回source数据!");
return source;
}
try {
for (String key : source.keySet()) {
Object value = source.get(key);
// 如果target中不包含该key,直接添加
if (!target.containsKey(key)) {
target.put(key, value);
continue;
}
// 如果值为JSONObject类型,递归合并
if (value instanceof JSONObject) {
JSONObject sourceValue = (JSONObject) value;
JSONObject targetValue = target.getJSONObject(key);
JSONObject mergedValue = jsonMerge(sourceValue, targetValue);
target.put(key, mergedValue);
continue;
}
// 如果值为JSONArray类型,遍历数组进行合并
if (value instanceof JSONArray) {
JSONArray sourceArray = (JSONArray) value;
JSONArray targetArray = target.getJSONArray(key);
// 确保两个数组长度一致
if (sourceArray.size() != targetArray.size()) {
throw new IllegalArgumentException("Arrays have different lengths for key: " + key);
}
for (int i = 0; i < sourceArray.size(); i++) {
Object sourceItem = sourceArray.get(i);
Object targetItem = targetArray.get(i);
// 只有当两个元素都是JSONObject时才进行合并
if (sourceItem instanceof JSONObject && targetItem instanceof JSONObject) {
JSONObject mergedItem = jsonMerge((JSONObject) sourceItem, (JSONObject) targetItem);
targetArray.set(i, mergedItem);
}
}
continue;
}
// 其他类型直接覆盖
target.put(key, value);
}
} catch (Exception e) {
// 记录错误日志
logger.error("JSON merge error", e);
// 可以考虑使用日志框架,如:logger.error("JSON merge error", e);
throw new RuntimeException("Error merging JSON objects", e);
}
return target;
}
/**
* 合并两个JSONArray,将array2的元素追加到array1的元素之后。
*
* @param array1 第一个JSONArray,优先保留
* @param array2 第二个JSONArray,将被追加到array1之后
* @return 合并后的新JSONArray,包含两个数组的所有元素
* @throws IllegalArgumentException 如果两个数组中存在非JSONObject元素
* @throws RuntimeException 如果合并过程中发生错误
*/
public static JSONArray jsonArrayMerge(JSONArray array1, JSONArray array2) {
// 参数校验
if (array1 == null) {
logger.error("参数array1为空,返回array2数据!");
return array2;
}
if (array2 == null) {
logger.error("参数array2为空,返回array1数据!");
return array1;
}
JSONArray mergedArray = new JSONArray();
try {
// 添加第一个数组的所有元素
addAllSafe(array1, mergedArray);
// 添加第二个数组的所有元素
addAllSafe(array2, mergedArray);
} catch (Exception e) {
// 记录错误日志
logger.error("JSON array merge error", e);
// 可以考虑使用日志框架,如:logger.error("JSON array merge error", e);
throw new RuntimeException("Error merging JSON arrays", e);
}
return mergedArray;
}
/**
* 深度复制一个JSONObject。
*
* @param source 要复制的JSONObject
* @return 深度复制后的JSONObject
*/
private static JSONObject deepCopy(JSONObject source) {
return JSON.parseObject(JSON.toJSONString(source));
}
/**
* 安全地将源数组的所有元素添加到目标数组。
*
* @param source 源JSONArray
* @param target 目标JSONArray
*/
private static void addAllSafe(JSONArray source, JSONArray target) {
for (Object item : source) {
// 检查元素类型,确保为JSONObject类型
if (item instanceof JSONObject) {
target.add(deepCopy((JSONObject) item));
} else if (item instanceof JSONArray) {
// 如果需要支持嵌套数组,可以递归处理
JSONArray nestedArray = new JSONArray();
addAllSafe((JSONArray) item, nestedArray);
target.add(nestedArray);
} else {
// 非对象元素直接添加
target.add(item);
}
}
}
public static JSONObject toJsonObject(String jsonString) {
return JSONObject.parseObject(jsonString);
}
/**
* 将json字符串转换为T
*/
public static <T> T fromJsonStringToT(String jsonString, Class<T> clazz) {
return JSONObject.parseObject(jsonString, clazz);
}
/**
* 将Object转换为字符串
*/
public static String toString(Object object) {
return JSONObject.toJSONString(object);
}
/**
* list对象转换为Json字符串,仅包含arrays中的属性值
*/
public static String listToStringIncludeArrays(List<?> list, String[] arrays) {
List<Object> result = new ArrayList<>();
for (Object object : list) {
Map<String, Object> map = objectToMapIncludeArrays(object, arrays);
result.add(map);
}
return JSONObject.toJSONString(result);
}
/**
* Object对象转换为json字符串,仅包含arrays中的属性值
*/
public static String objectToStringIncludeArrays(Object object, String[] arrays) {
Map<String, Object> result = objectToMapIncludeArrays(object, arrays);
return JSONObject.toJSONString(result);
}
private static Map<String, Object> objectToMapIncludeArrays(Object object, String[] arrays) {
Map<String, Object> result = new HashMap<>();
for (String array : arrays) {
// 如果需要转换的为Map对象,则直接从map中包含arrays的值放到新的map中
if (object instanceof Map) {
result.put(array, ((Map<?, ?>) object).get(array));
} else {
// 如果非map则从object中通过反射获取属性值,放到map中
try {
Object value = getFieldValueByObject(object, array);
result.put(array, value);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
return result;
}
private static Object getFieldValueByObject(Object object, String targetFieldName) throws Exception {
// 获取该对象的Class
Class<?> objClass = object.getClass();
// 获取所有的属性数组
Field[] fields = objClass.getDeclaredFields();
for (Field field : fields) {
// 属性名称
String currentFieldName = field.getName();
if (currentFieldName.equals(targetFieldName)) {
field.setAccessible(true);
// 通过反射拿到该属性在此对象中的值(也可能是个对象)
return field.get(object);
}
}
// 获取继承类里面的属性值
Class<?> superClass = objClass.getSuperclass();
if (null != superClass) {
Field[] superFields = superClass.getDeclaredFields();
for (Field superField : superFields) {
// 属性名称
String currentFieldName = superField.getName();
if (currentFieldName.equals(targetFieldName)) {
superField.setAccessible(true);
// 通过反射拿到该属性在此对象中的值(也可能是个对象)
return superField.get(object);
}
}
}
return null;
}
/**
* 判断是否jsonObj或者jsonArray格式字符串
*/
public static boolean isJsonStr(String jsonStr) {
try {
JSON.parse(jsonStr);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 用gson判断字符串是否是有效的Json串
*/
public static boolean isGsonStr(String jsonStr) {
try {
JsonParser.parseString(jsonStr);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 将json字符串转为map
*/
public static Map<String, Object> jsonToMap(String json) {
if (StringUtils.isBlank(json)) {
return null;
}
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = null;
try {
map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
} catch (JsonProcessingException e) {
logger.error("jsonToMap error: {}", e.getMessage());
throw new RuntimeException("Json To Map Error: " + e.getMessage());
}
return map;
}
/**
* json格式字符串转换为List的map
*/
public static List<Map<String, Object>> jsonToList(String json) {
if (StringUtils.isBlank(json)) {
return null;
}
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, Object>> list = null;
try {
list = objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {
});
} catch (JsonProcessingException e) {
System.err.println(e.getMessage());
}
return list;
}
/**
* *将json字符串转换为对象集合
*
* @param jsonString json字符串
* @param valueType 对象类型
**/
public static <T> List<T> jsonToList(String jsonString, Class<T> valueType) throws IOException {
if (StringUtils.isBlank(jsonString)) {
return null;
}
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(jsonString, objectMapper.getTypeFactory().constructCollectionType(List.class, valueType));
}
/**
* 获取JSONObject中指定字段的字符串值
*
* @param jsonObject JSONObject对象
* @param key 字段名
* @return 字段对应的字符串值,若字段不存在则返回空字符串
*/
public static String getString(JSONObject jsonObject, String key) {
return Objects.nonNull(jsonObject.getString(key)) ? jsonObject.getString(key) : "";
}
/**
* 获取JSONObject中指定字段的整数值
*
* @param jsonObject JSONObject对象
* @param key 字段名
* @return 字段对应的整数值,若字段不存在或无法转换为整数时返回0
*/
public static int getInt(JSONObject jsonObject, String key) {
return Objects.nonNull(jsonObject.getInteger(key)) ? jsonObject.getInteger(key) : 0;
}
/**
* 获取JSONObject中指定字段的布尔值
*
* @param jsonObject JSONObject对象
* @param key 字段名
* @return 字段对应的布尔值,若字段不存在或无法转换为布尔值时返回false
*/
public static boolean getBoolean(JSONObject jsonObject, String key) {
return Objects.nonNull(jsonObject.getBoolean(key)) ? jsonObject.getBoolean(key) : false;
}
/**
* 获取JSONObject中指定字段的JSONObject对象
*
* @param jsonObject JSONObject对象
* @param key 字段名
* @return 字段对应的JSONObject对象,若字段不存在或无法转换为JSONObject对象时返回null
*/
public static JSONObject getJsonObject(JSONObject jsonObject, String key) {
return Objects.nonNull(jsonObject.getJSONObject(key)) ? jsonObject.getJSONObject(key) : null;
}
/**
* 获取JSONObject中指定字段的JSONArray对象
*
* @param jsonObject JSONObject对象
* @param key 字段名
* @return 字段对应的JSONArray对象,若字段不存在或无法转换为JSONArray对象时返回null
*/
public static JSONArray getJsonArray(JSONObject jsonObject, String key) {
return Objects.nonNull(jsonObject.getJSONArray(key)) ? jsonObject.getJSONArray(key) : null;
}
/**
* 将对象转换为JSONObject对象
*
* @param obj 对象
* @return 转换后的JSONObject对象
*/
public static JSONObject objectToJson(Object obj) {
return JSON.parseObject(JSON.toJSONString(obj));
}
/**
* 将JSON字符串转换为JSONArray对象
*
* @param json JSON字符串
* @return 转换后的JSONArray对象,若转换失败则返回null
*/
public static JSONArray stringToJsonArray(String json) {
try {
return JSON.parseArray(json);
} catch (Exception e) {
logger.error("String To JsonArray error: {}", e.getMessage());
return null;
}
}
/**
* 将JSONArray对象转换为JSON字符串
*
* @param jsonArray JSONArray对象
* @return 转换后的JSON字符串
*/
public static String jsonArrayToString(JSONArray jsonArray) {
return jsonArray.toString();
}
/**
* 将JSONArray对象转换为指定类型的List集合
*
* @param jsonArray JSONArray对象
* @param clazz List集合的元素类型
* @return 转换后的List集合
*/
public static <T> List<T> jsonArrayToList(JSONArray jsonArray, Class<T> clazz) {
List<T> list = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
T item = null;
try {
item = clazz.newInstance();
if (item instanceof JSONObject) {
list.add((T) jsonArray.getJSONObject(i));
} else {
list.add((T) jsonArray.get(i));
}
} catch (Exception e) {
logger.error("jsonArrayToList error: {}", e.getMessage());
throw new RuntimeException("JsonArray To List Error: " + e.getMessage());
}
}
return list;
}
/**
* 将List集合转换为JSONArray对象
*
* @param list List集合
* @return 转换后的JSONArray对象
*/
public static JSONArray listToJsonArray(List<?> list) {
JSONArray jsonArray = new JSONArray();
for (Object obj : list) {
jsonArray.add(objectToJson(obj));
}
return jsonArray;
}
/**
* *将json字符串中的旧字符串替换成新字符串
*
* @param jsonString json字符串
* @param oldString 旧字符串
* @param newString 新字符串
**/
public static String replaceStringInJson(String jsonString, String oldString, String newString) {
try {
// 将json字符串转换为JSONObject对象
JSONObject json = JSON.parseObject(jsonString);
// 使用递归函数进行替换
replaceStringInJson(json, oldString, newString);
// 返回更新后的json字符串
return json.toString();
} catch (JSONException e) {
e.printStackTrace();
}
// 如果发生异常,则返回原始的json字符串
return jsonString;
}
/**
* *将json对象中的旧字符串替换成新字符串
*
* @param object JSONObject或JSONArray
* @param oldString 旧字符串
* @param newString 新字符串
**/
public static void replaceStringInJson(Object object, String oldString, String newString) {
if (object instanceof JSONObject) {
JSONObject json = (JSONObject) object;
// 遍历JSONObject的所有键
for (String key : json.keySet()) {
Object value = json.get(key);
// 如果键对应的值是字符串类型,则尝试替换旧字符串为新字符串
if (value instanceof String) {
String oldValue = (String) value;
String newValue = oldValue.replaceAll(oldString, newString);
// 更新键对应的值为新字符串
json.put(key, newValue);
} else {
replaceStringInJson(value, oldString, newString);
}
}
} else if (object instanceof JSONArray) {
JSONArray jsonArray = (JSONArray) object;
for (Object value : jsonArray) {
replaceStringInJson(value, oldString, newString);
}
}
}
}
七、总结
JsonUtil
工具类通过封装高频操作、处理边界情况、简化API调用,将开发者从重复的JSON处理代码中解放出来。无论是简单的格式转换,还是复杂的多源数据合并,都能通过一两行代码快速实现,且内置的空值处理、异常兜底机制大幅降低了线上故障风险。
在实际项目中,建议将JsonUtil
作为基础工具类集成,结合业务场景扩展功能(如添加敏感字段自动过滤规则)。掌握这款工具,不仅能提升开发效率,更能培养“封装复用”的编程思维——将重复工作抽象为工具,是进阶高级开发的关键能力。