處理JSON的Java API :JSON的簡介
原文連結 作者:Jitendra Kotamraju 譯者:撒木
處理JSON的各種解析、生成、處理、轉換和查詢的JAVA API
JSON (JavaScript Object Notation)是一種輕量級的、基於文字的、完全獨立於語言的資料交換格式。它非常方便人們和機器的閱讀和書寫。JSON 有兩種結構型別的表現方式:物件和陣列。物件是名/值對的無序集合。陣列是值(value)的有序集合。值的型別可以是字串(在雙引號中)、數字(整數或浮點數)、邏輯值(true或false)、陣列(在方括號中)、物件(在花括號中)、null。
列表1來自 Wikipedia 以JSON表示的一個物件去描述一個人。這個人的姓和名都是字串型別,一個數值表示了年齡,一個物件表示了這個人的地址,還有一個數組物件表示了電話號碼。
{ "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": 10021 }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "fax", "number": "646 555-4567" } ] }
列表 1. JSON表示物件的一個例子
JSON通常被用在Ajax應用、配置、資料庫和RESTful web services。幾乎所有流行的網站都提供了JSON的資料交換方式在他們的RESTful web services上。
處理JSON
處理JSON的Java API (JSR 353)提供了各種便捷的API,其中包括解析、生成、轉換和使用物件模 型或流來查詢JSON。
物件模型的API在記憶體中產生一個隨機存取的樹狀結構來代表了JSON資料。這個樹可以被操作和查詢。這種程式設計模型可以很靈活的處理需要隨機存取完整內容的樹。但是,物件模型通常都沒有流模型效率高,而且需要的儲存空間也比流模型多
流API提供了一種以流來解析和生成JSON的方法。它把解析生成JSON的控制權交給了程式猿。流API提供了一種基於事件的解析器並且允許開發者詢問下一個事件,而不是再一個回撥函式中負責事件的處理。它給予了開發者更多的處理JSON的過程控制。應用程式程式碼可以處理或拋棄解析器事件,也可以詢問下一個事件(pull the event)。流模型適合於部分不需要的資料的隨機存取的區域性處理。同樣的,流API提供了一種通過寫一次事件生成結構良好的JSON流。
物件模型API
物件模型API和檔案物件模型(DOM)API在xml中很相似。這是一個高階的API,它為JSON物件和陣列結構提供了不可變的物件模型。這些JSON結構通過使用 JsonObject
和JsonArray
被表示為物件模型。表格1中展示了物件模型API的主要的類和介面。
JsonObject提供了一個Map檢視去存取含有名/值對的無序集合。同樣的,JsonArray提供了一個List去存取含有值的有序序列。
表格 1.物件模型API中主要的類和介面
類和介面 | 描述 |
---|---|
Json |
包含產生JSON readers,writers,builders,和他們的工廠物件的靜態方法 |
JsonGenerator |
一次一個值的將JSON資料寫入一個流中。 |
JsonReader |
從流中讀取JSON資料,並且建立一個物件模型在記憶體中 |
JsonObjectBuilder JsonArrayBuilder |
在記憶體中通過向原始碼中加入一個值,建立一個物件模型或者陣列模型 |
JsonWriter |
從記憶體中拿出一個物件模型寫入流中 |
JsonValue JsonObject JsonArray JsonString JsonNumber |
表示JSON資料中的資料型別. |
JsonObject,JsonArray,JsonString 和JsonNumber 是JsonValue的子型別。他們是被定義在API中的常量,有null,true,false的JSON值。
物件模型API使用建造者設計模式,從頭建立這些物件模型。應用程式程式碼可以使用介面JsonObjectBuilder 來建立模型來代表JSON物件。由此產生的模型是JsonObject。應用程式程式碼可以使用介面JsonArrayBuilder來建立模型來代表JSON陣列。由此產生的模型JsonArray。
這些物件模型也可以從一個輸入源(例如InputStream或Reader)使用介面JsonReader來建立。同樣的,可以寫出到一個輸出源(例如OutputStream或Writer)使用類JsonWriter。
舉個例子,讓我們使用物件模型API寫個搜尋Facebook的公開崗位的code。Facebook的API給我們了搜尋結果在列表2中。
1 { 2 "data" : [ 3 { "from" : { "name" : "xxx", ... }, "message" : "yyy", ... }, 4 { "from" : { "name" : "ppp", ... }, "message" : "qqq", ... }, 5 ... 6 ], 7 ... 8 }
列表 2. 搜尋Facebook公開崗位的JSON示例
我們可以使用物件模型API取得關於JAVA的名字和他們的崗位。
在列表3中,
第3行建立了JsonReader;
第5行建立了返回結果的JsonObject;
第7行迴圈每一個結果;
第8-11行取得了公佈人的姓名和職位,並且列印它們
注意:JsonReader和其他API上的物件可以用於帶有資源的try語法中(這也叫做自動資源管理[ARM]).
1 URL url = new URL("https://graph.facebook.com/search?q=java&type=post"); 2 try (InputStream is = url.openStream(); 3 JsonReader rdr = Json.createReader(is)) { 4 5 JsonObject obj = rdr.readObject(); 6 JsonArray results = obj.getJsonArray("data"); 7 for (JsonObject result : results.getValuesAs(JsonObject.class)) { 8 System.out.print(result.getJsonObject("from").getString("name")); 9 System.out.print(": "); 10 System.out.println(result.getString("message", "")); 11 System.out.println("-----------"); 12 } 13 }
列表 3. 使用物件模型API處理Facebook的崗位。
流API
流API與XML的流API(StAX)類似,它是由介面JsonParser和JsonGenerator組成。JsonParser 包含使用流模型解析JSON資料的方法JsonGenerator包含輸出JSON資料到一個輸出源的方法。
表格2展示了流API中主要的類和介面
表格 2. 流API中主要的類
類或介面 | 描述 |
---|---|
Json |
包含建立JSON解析器,生成器,和工廠物件的靜態方法。 |
JsonParser |
表示一個基於事件的解析器,可以從流中讀取JSON資料。 |
JsonGenerator |
每次一個值將JSON資料寫出到流中 |
JsonParser提供了先鋒,使用pull 解析物件模型,訪問只讀的JSON資料。在這個模型中,應用程式程式碼在解析器介面中,控制執行緒和方法呼叫,來使解析器向前移動或者從當前解析器的狀態獲得JSON資料。
JsonGenerator提供了將JSON資料寫入流的方法。生成器可以在JSON物件中寫入名/值對,在JSON陣列中寫入值。
流API是一個低階的API,它被設計用來更效率的處理大量的JSON資料。其他的JSON框架(例如JSON binding) 通過使用API可以繼承(implement)。
讓我們使用流API來做一下剛才使用物件模型API做過的事情。搜尋Facebook的關於JAVA的崗位。
在列表4中,
第1-3行建立了一個流的解析器,
第4-5行取得了下一個事件
第6行尋找KEY_NAME這個事件,
第8到11行讀取名字並列印它們,
第14-16行讀取職位並輸出他們。
當使用物件模型API比較相同的工作,流API提供了一種有效的方式存取名字和職位。
1 URL url = new URL("https://graph.facebook.com/search?q=java&type=post"); 2 try (InputStream is = url.openStream(); 3 JsonParser parser = Json.createParser(is)) { 4 while (parser.hasNext()) { 5 Event e = parser.next(); 6 if (e == Event.KEY_NAME) { 7 switch (parser.getString()) { 8 case "name": 9 parser.next(); 10 System.out.print(parser.getString()); 11 System.out.print(": "); 12 break; 13 case "message": 14 parser.next(); 15 System.out.println(parser.getString()); 16 System.out.println("---------"); 17 break; 18 } 19 } 20 } 21 }
列表 4. 使用流API處理Facebook的崗位資訊
結論
處理JSON的Java API提供瞭如下功能:
- 將輸入流解析為不可變的物件或事件流
- 將事件流或不可變物件寫入輸出流中
- 程式設計操作不可變物件
- 使用builders程式設計構建不可變物件
構建資料繫結,轉換,查詢或其他的操作API基礎。JAX-RS 2.0 提供了原始整合為處理JSON的JAVA API。
參見
關於作者
Jitendra Kotamraju,Oracle技術人員的主要成員,是JSON處理規範領導和GlassFish之後的一個關鍵工程師。在領導JSON處理計劃之前,他負責JAX-WS 2.2 的規範和實現