首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 通用 JSON 遞歸解析器:任意層級結構自動轉 Map/List/String

     編輯:Java 相關知識

設計目標

針對結構不固定、層級任意的 JSON 字符串,無需定義 POJO,自動遞歸解析為 Java 集合結構:

  • JSON Object → Map<String, Object>
  • JSON Array → 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()國產、功能豐富極高高中等

注意事項

  1. 數字類型:org.json 解析數字為 Integer/Long/Double,轉字符串可能丟失精度(科學計數法),建議數值字段統一用 getInteger/getDouble 輔助方法。
  2. 大數組/深層嵌套:遞歸可能棧溢出,超大 JSON 改用流式解析器(Jackson Streaming API)。
  3. 日期/二進制:JSON 無原生類型,約定為字符串(ISO8601/Base64),解析後手動轉換。
  4. 線程安全:org.json 類非線程安全,多線程環境勿共享 JSONObject/JSONArray 實例。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved