上一篇
java json 怎么去除
- 后端开发
- 2025-08-04
- 47
Java中,可借助org.apache.commons.lang3包的StringEscapeUtils类的unescapeJava()方法去除JSON中的转义字符
Java中处理JSON数据时,去除特定内容是一个常见需求,例如去除外层键、空值或冗余字段,以下是详细的实现方法和示例代码,涵盖多种场景及主流库的使用技巧:
去除外层键(保留内部数据)
当JSON结构包含多余的外层包装时(如{"other": {...}}),可通过提取内部对象实现剥离,以下是两种主流方案:
使用org.json库
import org.json.JSONObject;
public class RemoveOuterKeyExample {
public static void main(String[] args) {
String json = "{"other": {"name": "john", "age": 30}}";
JSONObject jsonObject = new JSONObject(json); // 解析原始JSON
JSONObject innerObject = jsonObject.getJSONObject("other"); // 获取内部对象
System.out.println(innerObject.toString()); // 输出: {"name":"john","age":30}
}
}
此方法直接通过getJSONObject()定位子节点,适用于简单嵌套结构,需确保项目中已添加org.json依赖。

使用Jackson库
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonRemoveOuterLayer {
public static void main(String[] args) throws JsonProcessingException {
String json = "{ "other": { "name": "john doe", "email": "john.doe@example.com" } }";
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(json); // 读取为树形结构
JsonNode innerNode = rootNode.get("other"); // 提取目标节点
rootNode = innerNode; // 替换根节点
System.out.println(mapper.writeValueAsString(rootNode)); // 输出无外层键的结果
}
}
Jackson的优势在于灵活操作JsonNode,支持复杂路径遍历和动态修改,适合处理多层嵌套的数据。
移除值为空的键
实际开发中常需清理无效字段(如null、空字符串),以下是基于不同库的解决方案:

Jackson递归清洗方案
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CleanEmptyFields {
public static String removeEmptyKeys(String json) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(json);
removeEmptyNodes(rootNode); // 递归处理所有节点
return rootNode.toString();
} catch (Exception e) {
e.printStackTrace();
return json;
}
}
private static void removeEmptyNodes(JsonNode node) {
if (node.isObject()) {
Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
JsonNode child = entry.getValue();
// 判断是否为空值或空字符串
if (child.isNull() || (child.isTextual() && child.textValue().isEmpty())) {
iterator.remove(); // 删除无效字段
} else {
removeEmptyNodes(child); // 深度遍历子节点
}
}
} else if (node.isArray()) {
for (int i = 0; i < node.size(); i++) {
JsonNode child = node.get(i);
if (child.isNull() || (child.isTextual() && child.textValue().isEmpty())) {
((ArrayNode) node).remove(i); // 数组元素去重
i--; // 调整索引补偿删除操作
} else {
removeEmptyNodes(child);
}
}
}
}
}
该算法通过递归遍历所有层级,精准识别并删除各类空值,包括嵌套对象和数组中的无效项。
Gson实现方式
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class GsonCleaner {
public static String removeEmptyKeys(String json) {
try {
JsonElement root = JsonParser.parseString(json);
cleanNode(root);
return root.toString();
} catch (Exception e) {
e.printStackTrace();
return json;
}
}
private static void cleanNode(JsonElement element) {
if (element.isJsonObject()) {
JsonObject obj = element.getAsJsonObject();
for (String key : new ArrayList<>(obj.keySet())) { // 避免并发修改异常
JsonElement child = obj.get(key);
if (child.isJsonNull() || (child.isPrimitive() && child.getAsString().isEmpty())) {
obj.remove(key); // 移除空字段
} else {
cleanNode(child); // 递归处理子节点
}
}
} else if (element.isJsonArray()) {
for (int i = 0; i < element.getAsJsonArray().size(); i++) {
cleanNode(element.getAsJsonArray().get(i)); // 处理数组元素
}
}
}
}
Gson的API设计更贴近Java集合操作,适合熟悉Guava风格的开发者,注意需手动创建键副本以避免迭代时修改异常。

对比分析与选型建议
| 特性 | org.json | Jackson | Gson |
|---|---|---|---|
| API复杂度 | 简单直观 | 功能强大但稍复杂 | 简洁易用 |
| 性能 | 中等 | 最高(流式解析) | 较高 |
| 适用场景 | 快速原型开发 | 复杂数据处理 | 轻量级任务 |
| 依赖体积 | 较小 | 较大 | 中等 |
注意事项
- 数据类型一致性:确保操作前验证字段类型(如区分
null与空字符串); - 编码兼容性:处理非UTF-8字符集时需额外转码;
- 性能优化:大文件处理建议采用流式API而非全量加载;
- 错误处理:捕获
JsonProcessingException等异常以保证程序健壮性。
FAQs
Q1: 如何判断某个JSON字段是否存在且非空?
A: 使用Jackson的has()方法检查键是否存在,结合!node.isNull() && !node.asText().isEmpty()验证非空性。
if (rootNode.has("field") && !rootNode.get("field").isNull()) { ... }
Q2: 能否批量删除多个指定名称的外层键?
A: 可以遍历所有目标键名并依次提取对应子节点,以Jackson为例:
List<String> keysToRemove = Arrays.asList("wrapper1", "wrapper2");
for (String key : keysToRemove) {
if (rootNode.has(key)) {
rootNode = rootNode.get(key); // 逐层剥离多个外层键
