
本文介绍如何使用 gson 库高效地将扁平 json 对象中的所有键与对应值(支持数字和字符串)按原始顺序拼接成一个无分隔符的字符串,适用于日志标记、简易哈希输入等场景。
本文介绍如何使用 gson 库高效地将扁平 json 对象中的所有键与对应值(支持数字和字符串)按原始顺序拼接成一个无分隔符的字符串,适用于日志标记、简易哈希输入等场景。
在实际开发中,有时需要将 JSON 数据“扁平化”为紧凑的字符串形式(例如用于生成轻量标识符、调试摘要或兼容旧协议),而非标准格式化输出。本文聚焦一种典型需求:给定一个不含嵌套结构的 JSON 对象(如 {"Id": 200, "TimeStamp": 1596466800, "Animal": "cat"}),将其所有键(key)与对应值(value)严格按遍历顺序拼接为单个字符串,且不添加任何分隔符、空格或引号,最终得到类似 "Id200TimeStamp1596466800Animalcat" 的结果。
该任务看似简单,但需注意三点关键细节:
- JSON 值类型多样(字符串、数字、布尔值等),需统一转换为字符串表示;
- JsonObject.entrySet() 的遍历顺序不保证与原始 JSON 字符串中键的顺序一致(Java 8+ 的 LinkedHashMap 实现虽常保持插入序,但 Gson 默认解析器不保证——依赖此行为存在风险);
- 若需严格保序,应优先解析为 JsonElement 后手动按原始 token 流处理;但本方案面向常见扁平场景,在明确输入结构可控的前提下,采用简洁可靠的键值提取逻辑。
以下为基于 Gson 2.10+ 的完整实现:
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import java.util.Map;
import java.util.Set;
public class JsonKeyConcatenator {
public static String concatenateKeysAndValues(String json) {
JsonElement root = JsonParser.parseString(json);
if (!root.isJsonObject()) {
throw new IllegalArgumentException("Input must be a valid JSON object");
}
JsonObject jsonObject = root.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entries = jsonObject.entrySet();
StringBuilder result = new StringBuilder();
for (Map.Entry<String, JsonElement> entry : entries) {
String key = entry.getKey();
JsonElement value = entry.getValue();
// 确保值为基本类型(非 null、对象、数组)
if (!value.isJsonPrimitive()) {
throw new UnsupportedOperationException(
"Unsupported value type for key '" + key + "': " + value.getClass().getSimpleName()
);
}
JsonPrimitive primitive = value.getAsJsonPrimitive();
result.append(key);
if (primitive.isString()) {
result.append(primitive.getAsString());
} else if (primitive.isNumber()) {
// 使用 toString() 避免科学计数法(如 1e9 → "1000000000")
result.append(primitive.getAsNumber().toString());
} else if (primitive.isBoolean()) {
result.append(primitive.getAsBoolean());
} else {
throw new UnsupportedOperationException("Unsupported primitive type: " + primitive);
}
}
return result.toString();
}
// 示例用法
public static void main(String[] args) {
String input = "{ \"Id\": 200, \"TimeStamp\": 1596466800, \"Animal\": \"cat\" }";
String output = concatenateKeysAndValues(input);
System.out.println(output); // 输出:Id200TimeStamp1596466800Animalcat
}
}✅ 关键特性说明:
- 显式校验输入是否为 JSON 对象,并对非基本类型值抛出清晰异常;
- 支持字符串、整数/浮点数、布尔值三种常用 JsonPrimitive 类型;
- 数字调用 .getAsNumber().toString() 而非 .getAsBigDecimal(),避免潜在精度丢失与依赖 BigDecimal 的冗余;
- 方法抽取为静态工具函数,便于复用与单元测试。
⚠️ 注意事项:
- 顺序不可靠性:Gson 的 JsonObject.entrySet() 返回的 Set 不保证顺序。若原始 JSON 键序至关重要(如 "a":1,"b":2 必须生成 "a1b2" 而非 "b2a1"),建议改用 JsonReader 手动流式解析,或选用保留顺序的库(如 Jackson 的 JsonNode.fields() 配合 LinkedHashMap);
- 嵌套与空值:本方案不处理嵌套对象、数组或 null 值。如需支持,需递归展开或定义降级策略(如跳过、替换为占位符);
- 性能考量:对于高频调用场景,可预编译 JsonParser 实例或缓存 JsonObject,但需注意线程安全性。
总结而言,该方案以最小依赖、清晰逻辑和强类型校验,精准满足“扁平 JSON 键值无缝拼接”的核心诉求。在输入结构受控的业务场景(如配置快照、事件摘要生成)中,兼具实用性与可维护性。










