《Android》『JSON & GSON』- JSON 的基本程式語法教學 (上)
《Android Developers 參考文獻》
《簡單介紹》
JSON 的全名稱作 JavaScript Object Notation,它是一種輕量級的資料交換格式,其語法格式僅包含兩種規則,分別是物件 {…} 與陣列 […],透過這種簡單明瞭的格式,我們可以在資料傳遞時使用最小的帶寬,並易於程式開發者解析與讀取資料。
而 GSON 是什麼呢?在 JSON 的官網上,提供了對於不同程式語言用來解析 JSON 格式資料的 API,而其中對於 Java 語言所提供的 API 中,有一個是 Google 專門為解析 JSON 格式的資料所開發的,其名稱便是 GSON。
簡單來說,JSON 是一種資料傳輸的格式,而 GSON 則是 Google 所提供的 API,用來更加快速的解析 JSON 格式的資料。
《JSON、XML、HTML 之差異》
XML 與 JSON 一樣,是用來做資料傳輸的一種交換格式,但當資料量很多時,XML 的缺點就出現了,多層標籤包裹的 XML 會變得很肥大,不僅格式複雜且在資料傳遞時佔用了許多帶寬,與之相比,JSON 的數據格式比較簡單,易於讀寫,亦解決了資料過於複雜且龐大的問題。
XML 是一種類似於 HTML 的標記語言,但和 HTML 卻是兩種完全不同用途的語言,簡單來說,XML 是被設計用來描述資料的語言,HTML 則是被設計用來顯示資料的語言。
《JSON 之資料格式》
JSON 身為一種輕量級的資料交換語言,其格式十分簡單,分為物件 (object) 與陣列 (array) 兩種,分別說明如下 –
物件(object) – {} JSONObject
以物件格式儲存的資料,本身沒有順序性,其資料格式是一個名稱 (key) 對應一個值 (value) 所組成,其中名稱必須為字串,值則可以為字串、數字、布林值或是 null,在格式語法上以大括號表示。
資料格式範例如下 :
1 2 3 4 5 6 7 8 9 10 11 |
{ "author" : "Xylon", "score" : 100, "isHandsome" : true, "languages":[ {"id":1,"ide":"Eclipse","name":"Java"}, {"id":2,"ide":"Xcode","name":"Swift"}, {"id":3,"ide":"Visual Studio","name":"C#"} ], } |
物件資料格式
陣列(array) – [] JSONArray
以陣列格式儲存的資料,本身具有順序性,因此不需要為每個值訂一個名稱亦可以取到所需的值,我們可以在其中直接儲存字串、數字、布林值等資料,亦可以將物件格式或者陣列格式的資料當作一個值儲存在裡面,形成類似巢狀資料的效果,在格式語法上以中括號表示。
資料格式範例如下 :
1 2 3 4 5 6 7 8 9 10 |
[ "Nina", 90, false, { "author" : "Xylon", "score" : 100, "isHandsome" : true } ] |
陣列資料格式
《JSON 之資料解析基本用法》
JSON 對應不同的程式語言提供了用以解析其格式資料的 API,透過這些工具,我們可以在程式碼中對於 JSON 格式的資料進行解析,這邊直接以程式碼片段的方式,說明在 Java 中如何解析 JSON 的資料,以及如何將現有的資料物件轉換成 JSON 格式的資料。
1. 基本的 Json 與字串格式互轉方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public class Book { private String name; private double price; private String author; public Book() { super(); } public Book(String name, double price, String author) { super(); this.name = name; this.price = price; this.author = author; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public void show() { System.out.println("name = " + name + "; price = " + price + "; author = " + author); } } |
Book.java
首先,我們定義了一個名為 Book 的類別,其中包含了書名、作者與價格三個參數,值得注意的是,當我們將自訂的類別生成物件並轉存成 JSON 格式的字串後,在 JSON 字串裡的物件資料格式,其名稱(key)即是參照到我們物件裡所定義的參數名稱。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import org.json.JSONObject; . . . String jsonStr = ""; // Data for testing Book book1 = new Book("Java", 500, "John"); Book book2 = new Book("Android", 600, "Allen"); // Object to JSON jsonStr = new JSONObject(book1).toString(); System.out.println("Object to JSON: " + jsonStr); // JSON to Object JSONObject jsonObj = new JSONObject(jsonStr); String name = jsonObj.getString("name"); double price = jsonObj.getDouble("price"); String author = jsonObj.getString("author"); Book myBook = new Book(name, price, author); myBook.show(); System.out.println(); . . . |
mainActivity.java
接著,我們宣告了兩個基於 Book 類別的物件資料,分別命名為 book1 與 book2,並設定好初始資料,再透過 JSON 所提供的 JSONObject 類別,將 book1 與 book2 這兩個物件資料轉成 JSON 格式的字串,接著再把這個字串透過 JSONObject 類別所生成的物件 jsonObj,解析出我們所需要的資料,這邊要注意的是,我們所 import 的 JSONObject 為 Json 原生的類別(在 Gson 中也有一個一樣名字不過是小寫的 JsonObject 類別,所包含的函式名稱會不太一樣 (import com.google.gson.JsonObject)。
2. 一次要解析多筆物件格式之 Json 與字串格式互轉方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
. . . // Data for testing Book book1 = new Book("Java", 500, "John"); Book book2 = new Book("Android", 600, "Allen"); List<Book> bookList = new ArrayList<Book>(); bookList.add(book1); bookList.add(book2); // List to JSON jsonStr = new JSONArray(bookList).toString(); System.out.println("List to JSON: " + jsonStr); // JSON to List List<Book> books = new ArrayList<Book>(); JSONArray jsonArray = new JSONArray(jsonStr); for (int i = 0; i < jsonArray.length(); i++) { JSONObject json_book = jsonArray.getJSONObject(i); String book_name = json_book.getString("name"); double book_price = json_book.getDouble("price"); String book_author = json_book.getString("author"); Book book = new Book(book_name, book_price, book_author); books.add((book)); } for (Book book : books) { book.show(); } System.out.println(); . . . |
mainActivity.java
若是一次要解析多筆物件格式的資料,我們可以先宣告一個 ArrayList,將所有物件存入以後,再透過 JSONObject 類別與 JSONArray 類別來加以解析。
3. 程式裡所宣告的資料物件本身帶有 List 型別之 Json 與字串格式互轉方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
public class Order { private String orderId; private String customer; private Date date; private List<Book> bookList; public Order() { super(); } public Order(String orderId, String customer, Date date, List<Book> bookList) { super(); this.orderId = orderId; this.customer = customer; this.date = date; this.bookList = bookList; } public String getOrderId() { return orderId; } public void setOrderId(String orderId) { this.orderId = orderId; } public String getCustomer() { return customer; } public void setCustomer(String customer) { this.customer = customer; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public List<Book> getBookList() { return bookList; } public void setBookList(ArrayList<Book> bookList) { this.bookList = bookList; } public void show() { System.out.println("Order information:"); System.out.println("orderId = " + orderId + "; customer = " + customer + "; date = " + date); System.out.println("Details: "); for (Book book : bookList) { book.show(); } } } |
Order.java
還有一種可能,就是程式裡所宣告的資料物件本身帶有 List 型別的資料,我們同樣也可以利用 JSONObject 類別與 JSONArray 類別來加以解析,首先,我們定義了一個名為 Order 的類別,其中包含了訂單、客戶、購買時間與購買清單四個參數,其中購買清單是一個 List 型別的參數,用以存放多個 Book 類別的物件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Data for testing Book book1 = new Book("Java", 500, "John"); Book book2 = new Book("Android", 600, "Allen"); List<Book> bookList = new ArrayList<Book>(); bookList.add(book1); bookList.add(book2); Order order = new Order("111", "ron", new Date(), bookList); // Object (with List) to JSON jsonStr = new JSONObject(order).toString(); System.out.println("Object (with List) to JSON: " + jsonStr); // JSON to Object (with List) JSONObject orderObj = new JSONObject(jsonStr); String orderId = orderObj.getString("orderId"); String customer = orderObj.getString("customer"); // Locale.ENGLISH could be needed if current locale != ENGLISH // pattern letters refers to SimpleDateFormat in Javadoc SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy", Locale.ENGLISH); Date date = simpleDateFormat.parse(orderObj.getString("date")); JSONArray jsonArray_books = orderObj.getJSONArray("bookList"); List<Book> myBookList = new ArrayList<Book>(); for (int i = 0; i < jsonArray_books.length(); i++) { JSONObject json_book = jsonArray_books.getJSONObject(i); String bookName = json_book.getString("name"); double bookPrice = json_book.getDouble("price"); String bookAuthor = json_book.getString("author"); Book book = new Book(bookName, bookPrice, bookAuthor); myBookList.add((book)); } Order myOrder = new Order(orderId, customer, date, myBookList); myOrder.show(); |
mainActivity.java
只要注意好不同階層之間的節點關係,再利用 for 迴圈,我們就可以從 JSON 字串中取得所有想要的資料。另外,JSONObject 型別的物件,也可以透過 put(String key, value)、 與 remove(String key) 來新增子節點或刪除特定 key 值的節點。
下一篇我們再來利用 GSON,更加快速的解析 JSON 格式的資料。
現在好像不允許這樣做了
要改用gson轉型
Gson gson = new Gson();
String loginStr = gson.toJson(book1);
不好意思 想請問一下 我在mainactivity輸入 jsonStr = new JSONObject(book1).toString(); 它一直顯示cannot resolved constructor JSONObject(com.example.danny.Book) 請問是有需要加什麼東西嗎?
可能是你的 book1 物件結構有問題導致無法解析成 Json 字串?!