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

JSON 轉換為 Java 物件完整實作範例

     編輯:Java 相關知識

JSON 字串轉 Java 物件:從零打造解析器

在 Java 開發中,將 JSON 字串轉換為 Java 物件是常見需求。雖然成熟的庫如 Jackson、Gson 已非常好用,但理解底層解析邏輯對於排查疑難雜症、處理非標準 JSON 格式大有裨益。本文將帶你從零實作一個簡易且功能完整的 JSON 解析器,支援物件、陣列、巢狀結構及基本型別。

核心設計思路

解析器採用遞歸下降策略,主流程如下:

  1. 型別判斷:根據首尾字元(`{}`、`[]`、其它)判斷是 Map、List 還是純值。
  2. Token 化處理:逐字元掃描,處理引號、括號、冒號、逗號等結構符號,分離 key/value。
  3. 遞歸解析:遇到巢狀 `{}` 或 `[]` 時遞歸呼叫解析方法,構建完整物件樹。

完整程式碼實作

import java.util.*;
import com.jfinal.kit.JsonKit;

public class JsonToJavaObject {

    public static void main(String[] args) {
        String json = "{\"aa\":123,\"cc\":[1,2,3,4,{\"cd\":\"f\",\"bb\":234}]}";
        Object obj = parse(json);
        System.out.println(JsonKit.toJson(obj)); // 驗證輸出
    }

    public static Object parse(String json) {
        if (json == null) return null;
        json = json.trim();
        String type = typeof(json);
        switch (type) {
            case "map":  return parseMap(json);
            case "list": return parseList(json);
            default:     return json; // 純值直接返回
        }
    }

    private static Map parseMap(String json) {
        if (!"map".equals(typeof(json))) throw new RuntimeException("非 Map 格式");
        Map map = new HashMap<>();
        parseToken(map, json, null);
        return map;
    }

    private static List parseList(String json) {
        if (!"list".equals(typeof(json))) throw new RuntimeException("非 List 格式");
        List list = new ArrayList<>();
        parseToken(null, json, list);
        return list;
    }

    private static String typeof(String json) {
        if (json.isEmpty()) return "string";
        char first = json.charAt(0), last = json.charAt(json.length() - 1);
        if (first == '{' && last == '}') return "map";
        if (first == '[' && last == ']') return "list";
        return "string";
    }

    private static void parseToken(Map map, String json, List list) {
        boolean inDQuote = true, inSQuote = true, inBrace = true, inBracket = true;
        boolean isKey = true;
        StringBuffer key = new StringBuffer(), value = new StringBuffer();

        for (int i = 1; i < json.length() - 1; i++) {
            char c = json.charAt(i);

            // 處理大括號
            if (inDQuote && inSQuote && inBracket) {
                if (c == '{' || c == '}') inBrace = !inBrace;
            }
            // 處理中括號
            if (inDQuote && inSQuote && inBrace) {
                if (c == '[' || c == ']') inBracket = !inBracket;
            }
            // 處理雙引號
            if (inSQuote && inBrace && inBracket) {
                if (c == '"') { inDQuote = !inDQuote; continue; }
            }
            // 處理單引號
            if (inDQuote && inBrace && inBracket) {
                if (c == '\'') { inSQuote = !inSQuote; continue; }
            }

            // 結構分隔符(僅在最外層生效)
            if (inDQuote && inSQuote && inBrace && inBracket) {
                if (list == null && c == ':') { isKey = false; continue; } // Map 的 key/value 分隔
                if (c == ',') { // 鍵值對或陣列元素結束
                    if (map != null) map.put(key.toString(), parse(value.toString()));
                    if (list != null) list.add(parse(key.toString()));
                    key = new StringBuffer(); value = new StringBuffer(); isKey = true; continue;
                }
            }

            // 累積字元
            if (isKey) key.append(c); else value.append(c);
        }

        // 處理最後一組
        if (!key.toString().trim().isEmpty()) {
            if (map != null) {
                if (value.toString().trim().isEmpty()) throw new RuntimeException("JSON 格式錯誤");
                map.put(key.toString(), parse(value.toString()));
            }
            if (list != null) list.add(parse(key.toString()));
        }
    }
}


測試輸入與輸出

輸入:

{"aa":"123","cc":["1","2","3","4",{"bb":"234","cd":"f"}]}

輸出(經 JsonKit 序列化後):

{"aa":"123","cc":["1","2","3","4",{"bb":"234","cd":"f"}]}

適用場景與注意事項

  • 適合學習 JSON 解析原理、處理非標準 JSON(如無引號 key、單引號字串)。
  • 生產環境建議直接使用 Jackson / Gson,效能與健壯度更優。
  • 此實作未處理轉義字元、Unicode、數值科學記號等細節,若需完整相容 RFC 8259 請擴充 parseToken 邏輯。

掌握手寫解析器,能在面對「髒資料」或「受限環境無法引入第三方庫」時遊刃有餘。完整原始碼可直接複製至 IDE 執行驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved