
本文介绍如何利用 jackson 的 jsonnode api 递归遍历任意嵌套结构的 json,将所有字符串类型的字段值统一截断为最多 5 个字符,支持对象、数组及混合嵌套场景。
本文介绍如何利用 jackson 的 jsonnode api 递归遍历任意嵌套结构的 json,将所有字符串类型的字段值统一截断为最多 5 个字符,支持对象、数组及混合嵌套场景。
在实际开发中,常需对动态 JSON 数据进行标准化处理,例如日志脱敏、前端展示截断或数据库字段长度约束预校验。Jackson 作为主流 JSON 处理库,提供了灵活的树模型(JsonNode)用于无 Schema 场景下的结构化操作。以下方案基于 ObjectMapper.readTree() 构建可变树节点(ObjectNode/ArrayNode),通过深度优先递归遍历,精准识别并截断所有原始字符串值(JsonNodeType.STRING),同时安全跳过数字、布尔、null 及容器节点。
核心实现逻辑如下:
- 递归入口:接收任意 JsonNode,区分数组、对象、叶子值三类节点;
- 数组处理:遍历每个元素,递归调用自身;
- 对象处理:遍历所有字段,对非容器型子节点(即字符串、数字等)判断类型;仅当为字符串时执行 substring(0, Math.min(5, text.length())) 截断,避免 StringIndexOutOfBoundsException;
- 健壮性保障:使用 asText() 安全获取字符串表示(对 null 返回 ""),并始终取 Math.min(5, len) 长度,兼容超短字符串(如 "" 或 "a")。
以下是完整可运行示例代码:
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Iterator;
import java.util.Map.Entry;
public class JsonStringTruncator {
private static final int MAX_STRING_LENGTH = 5;
public static String truncateAllStringValues(String jsonInput)
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonInput);
truncateStringValues(root);
return mapper.writeValueAsString(root);
}
private static void truncateStringValues(JsonNode node) {
if (node == null || node.isMissingNode()) return;
if (node.isArray()) {
for (JsonNode element : node) {
truncateStringValues(element);
}
} else if (node.isObject()) {
ObjectNode objectNode = (ObjectNode) node;
Iterator<Entry<String, JsonNode>> fields = objectNode.fields();
while (fields.hasNext()) {
Entry<String, JsonNode> field = fields.next();
JsonNode value = field.getValue();
if (value.isValueNode() && value.isTextual()) {
String text = value.asText();
String truncated = text.substring(0, Math.min(MAX_STRING_LENGTH, text.length()));
objectNode.put(field.getKey(), truncated);
} else if (value.isContainerNode()) {
truncateStringValues(value);
}
}
}
}
// 使用示例
public static void main(String[] args) throws JsonProcessingException {
String input1 = "{\"key1\":\"bla bla bla bla\",\"key2\":{\"key21\":\"bla bla bla\"}}";
System.out.println(truncateAllStringValues(input1));
// 输出: {"key1":"bla b","key2":{"key21":"bla b"}}
String input2 = "{\"fname\":\"John Doe\",\"address\":{\"street\":\"123 Main St\",\"zip\":12345}}";
System.out.println(truncateAllStringValues(input2));
// 输出: {"fname":"John ","address":{"street":"123 M","zip":12345}}
}
}⚠️ 注意事项:
- 该方法不修改原始 JSON 的结构、键名、数字/布尔值或 null 值,仅作用于字符串文本内容;
- 若需保留原始格式缩进,可在 writeValueAsString() 前配置 mapper.enable(SerializationFeature.INDENT_OUTPUT);
- 对含 Unicode 多字节字符(如中文)的字符串,String.substring() 按 Java 字符(char)计数,非字节或码点;若需严格按 UTF-8 字节数截断,应改用 java.nio.charset.StandardCharsets.UTF_8 编码后处理;
- 生产环境建议封装为工具类,并增加空值与异常日志防护。
此方案简洁高效,适用于日志清洗、API 响应预处理、测试数据生成等场景,是 Jackson 树模型典型实战用例。


















