HOWTO · Java

在 Java 中處理 JSON 陣列

本文討論 JSON 框架、其結構、資料型別及其在 Java 中的使用。

本頁內容

若要在 Java 中讀取檔案裡的 JSON 陣列,請在專案中加入 JSON.simple 等 JSON 剖析器、剖析檔案,再走訪產生的陣列。Java 的標準程式庫不包含通用的 JSON 剖析器。JSON.simple 是外部相依套件,請透過專案使用的建置工具或相依套件管理工具加入。

JSON.simple 有過多個版本與 API 系列。下方範例使用 org.json.simple API 系列;使用前,請先選定版本,並查閱該版本的文件,確認相依套件座標、剖析器 API 與值的型別。本文不假設特定版本或建置工具。如果所選版本使用不同的套件或方法簽章,請依照該版本的文件調整範例,不要直接複製不相干的相依套件宣告。

在 Java 中處理 JSON 陣列

JSON(JavaScript Object Notation,JavaScript 物件標記法)使用物件、陣列、字串、數字、布林值和 null 表示資料。Java 程式需要透過剖析器,才能將 JSON 文字轉換成可供程式使用的值。JSON.simple 是執行這項剖析工作的其中一種選擇。

陣列是以方括號括住的有序序列;物件則是以大括號括住、由名稱和值組成的集合。陣列和物件可以彼此巢狀,因此檔案的最外層可能是陣列,其中的元素是物件,而每個物件又包含其他陣列或物件。

Java 中的 JSON 物件與 JSON 陣列

物件會以字串作為鍵來儲存值,每個鍵和值之間以冒號分隔,各項目之間則以逗號分隔。陣列依位置儲存值,項目之間也以逗號分隔。例如,行內 JSON 值 [1, "abc", {"name":"xyz"}] 是一個包含數字、字串和物件的陣列。該物件有一個 name 鍵,其值是字串。

範例使用的檔案最外層是含有一個物件的陣列。該物件包含字串、數字、兩個巢狀陣列和一個巢狀物件:

[{"name":"MMN","roll":24,"marks":[91,95,97,97,94],"parents":{"name":"IMT","mobile":"1234567890"},"hobbies":["sports","reading","music"],"others":["A",1]}]

資料結構會影響值的擷取方式:讀取 name、roll 或 parents 的程式碼,假設這些鍵存在,而且存放預期的 JSON 型別。如果輸入資料不受你控制,請先驗證每個值,再將它視為特定的 Java 型別。

在 Java 中使用 JSON.simple 從檔案讀取 JSON 陣列

請透過專案的相依套件管理工具加入 JSON.simple。使用所選確切版本文件所記載的套件座標;本文不指定座標,因為沒有指定特定版本或建置工具。org.json.simple 套件系列屬於外部套件,因此在 Java-only 環境中,若 classpath 未包含相符的程式庫,就無法執行其匯入項目與剖析器呼叫。

若專案使用相容版本的 JSON.simple,剖析步驟在概念上可表示為 new JSONParser().parse(reader)。請查閱該版本的文件,確認確切的剖析器 API 與回傳的集合型別。下方範例著重在下一個步驟:剖析器產生 Java 集合結構後,如何走訪該結構。範例中的值與上方的範例檔案相符,且只使用 Java 標準程式庫中的集合,因此可以獨立執行。

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class JSONArrayTraversal {
  public static void main(String[] args) {
    Map<String, Object> parents = new LinkedHashMap<>();
    parents.put("name", "IMT");
    parents.put("mobile", "1234567890");

    Map<String, Object> record = new LinkedHashMap<>();
    record.put("name", "MMN");
    record.put("roll", 24);
    record.put("marks", Arrays.asList(91, 95, 97, 97, 94));
    record.put("parents", parents);
    record.put("hobbies", Arrays.asList("sports", "reading", "music"));
    record.put("others", Arrays.asList("A", 1));
    List<Map<String, Object>> records = Arrays.asList(record);

    for (Map<String, Object> item : records) {
      System.out.println("Name: " + item.get("name"));
      System.out.println("Roll: " + item.get("roll"));
      System.out.println("Marks: " + item.get("marks"));
      System.out.println("Hobbies: " + item.get("hobbies"));
      Map<?, ?> parent = (Map<?, ?>) item.get("parents");
      System.out.println("Parent's Name: " + parent.get("name")
          + ", Mobile: " + parent.get("mobile"));
      System.out.println("Others: " + item.get("others"));
    }
  }
}
Name: MMN
Roll: 24
Marks: [91, 95, 97, 97, 94]
Hobbies: [sports, reading, music]
Parent's Name: IMT, Mobile: 1234567890
Others: [A, 1]

在實際應用程式中,請將所選 JSON.simple 剖析器回傳的值傳給走訪程式碼,並依該版本的集合型別調整程式碼。此處的 records 代表剖析後最外層的陣列。型別轉換與欄位查找都依賴範例的結構;如果輸入可能變動,請先驗證每個陣列元素與欄位,再依賴其型別。剖析期間請保持 reader 開啟,並在剖析完成後關閉,即使剖析失敗也一樣。請依所選版本文件記載的行為及應用程式需求,處理檔案存取與剖析失敗。將走訪程式碼連接到檔案輸入時,請提供環境中確實存在且可讀取的路徑。

結論

JSON 陣列是有序序列;JSON 物件則使用鍵來對應具名值。若要在 Java 中從檔案讀取 JSON 陣列,請使用 JSON.simple 等外部剖析器,將該版本文件記載的相依套件加入專案,再依輸入資料結構走訪剖析後的內容。使用型別轉換或值轉換之前,請先確認所選版本的 API 與數值型別。