針對結構不固定、層級任意的 JSON 字符串,無需定義 POJO,自動遞歸解析為 Java 集合結構:
Map<String, Object>List<Object>String / Number / Boolean<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.*;
public class JsonParser {
/** 入口:解析任意 JSON 字符串 */
public static Object parse(String jsonStr) {
if (jsonStr == null || jsonStr.trim().isEmpty()) {
throw new IllegalArgumentException("JSON 字符串不能為空");
}
// 提取首個 { 或 [ 到最後對應 } 或 ],兼容前後雜質
String trimmed = jsonStr.trim();
int start = Math.min(
trimmed.indexOf('{') == -1 ? Integer.MAX_VALUE : trimmed.indexOf('{'),
trimmed.indexOf('[') == -1 ? Integer.MAX_VALUE : trimmed.indexOf('[')
);
int end = Math.max(
trimmed.lastIndexOf('}'),
trimmed.lastIndexOf(']')
);
if (start <= end) {
trimmed = trimmed.substring(start, end + 1);
}
return parseValue(trimmed);
}
private static Object parseValue(String json) {
try {
if (isJsonObject(json)) {
return parseObject(json);
} else if (isJsonArray(json)) {
return parseArray(json);
}
} catch (JSONException e) {
// 忽略,作為基本類型處理
}
// 基本類型:去除引號、轉義
return unquote(json);
}
private static Map<String, Object> parseObject(String json) throws JSONException {
JSONObject obj = new JSONObject(json);
Map<String, Object> map = new LinkedHashMap<>(); // 保持順序
Iterator<String> keys = obj.keys();
while (keys.hasNext()) {
String key = keys.next();
map.put(key, parseValue(obj.get(key).toString()));
}
return map;
}
private static List<Object> parseArray(String json) throws JSONException {
JSONArray arr = new JSONArray(json);
List<Object> list = new ArrayList<>(arr.length());
for (int i = 0; i < arr.length(); i++) {
list.add(parseValue(arr.get(i).toString()));
}
return list;
}
private static boolean isJsonObject(String json) {
try {
new JSONObject(json);
return true;
} catch (JSONException ignored) {}
return false;
}
private static boolean isJsonArray(String json) {
try {
new JSONArray(json);
return true;
} catch (JSONException ignored) {}
return false;
}
private static String unquote(String s) {
if (s == null) return null;
s = s.trim();
if (s.length() >= 2 && ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'")))) {
return s.substring(1, s.length() - 1)
.replace("\\\"", "\"")
.replace("\\'", "'")
.replace("\\\\", "\\")
.replace("\\n", "\n")
.replace("\\r", "\r")
.replace("\\t", "\t");
}
return s;
}
}
String json = "{ \"user\": { \"name\": \"Alice\", \"age\": 30, \"tags\": [\"dev\", \"java\"] }, \"active\": true }";
Object result = JsonParser.parse(json);
if (result instanceof Map) {
Map<String, Object> root = (Map<String, Object>) result;
Map<String, Object> user = (Map<String, Object>) root.get("user");
System.out.println("Name: " + user.get("name")); // Alice
System.out.println("Age: " + user.get("age")); // 30
List<Object> tags = (List<Object>) user.get("tags");
System.out.println("Tags: " + tags); // [dev, java]
System.out.println("Active: " + root.get("active")); // true
}
public static String getString(Map<String, Object> map, String key) {
Object v = map.get(key);
return v == null ? null : v.toString();
}
public static Integer getInteger(Map<String, Object> map, String key) {
Object v = map.get(key);
if (v instanceof Number) return ((Number) v).intValue();
if (v instanceof String) return Integer.parseInt((String) v);
return null;
}
public static List<String> getStringList(Map<String, Object> map, String key) {
Object v = map.get(key);
if (v instanceof List) {
List<String> list = new ArrayList<>();
for (Object o : (List<?>) v) list.add(o.toString());
return list;
}
return Collections.emptyList();
}
| 方案 | 適用場景 | 性能 | 易用性 | 依賴 |
|---|---|---|---|---|
| 本文遞歸解析 (org.json) | 無 POJO、動態結構、臨時解析 | 中等 | 高(無需定義類) | 輕量 |
| Jackson ObjectMapper.readTree() | 高性能、流式、樹模型 | 高 | 中(JsonNode API) | 較大 |
| Gson JsonParser.parseString() | 樹模型、類型適配 | 高 | 中 | 中等 |
| FastJSON JSONObject.parseObject() | 國產、功能豐富 | 極高 | 高 | 中等 |
Integer/Long/Double,轉字符串可能丟失精度(科學計數法),建議數值字段統一用 getInteger/getDouble 輔助方法。