天天看點

Java開發筆記(一百零八)JSON串的定義和解析

前面提到URL尾巴支援添加請求參數,具體格式形如“參數A名稱=A參數值&參數B名稱=B參數值”,可是這種格式隻能傳遞簡單的鍵值對資訊,不能傳遞結構化資料,也無法傳遞數組形式的參數,因而它不适用于需要輸入複雜參數的場合。為此人們發明了一種輕量級的資料交換格式JSON,它的資料格式完全獨立于程式設計語言,不但能夠表達尋常的鍵值對資訊,還支援表達數組形式的各類參數,進而滿足了複雜參數的傳輸要求。

不過Java的開發包并未提供相應的工具來處理JSON串,為此我們需要在工程中添加第三方JSON解析庫,常見的json處理工具有阿裡巴巴的FastJson,它的下載下傳頁面是http://repo1.maven.org/maven2/com/alibaba/fastjson/,最新的版本已經疊代到了1.2.56。若想在代碼中使用FastJson的工具,則需先将它的jar包添加到工程的支援庫,右擊Eclipse左邊項目視圖中的工程名稱,在右鍵菜單中依次選擇“Build Path”——“Configure Build Path …”。在彈出的新視窗中單擊右邊的Libraries頁籤,接着單擊右側的“Add JARs…”按鈕,在另一個彈窗中找到fastjson-1.2.56.jar,如下圖所示。

Java開發筆記(一百零八)JSON串的定義和解析

然後單擊OK按鈕,回到前一個彈窗也單擊OK按鈕,完成FastJson的支援庫引入操作。

接下來浏覽一個購物訂單的JSON串例子,具體内容見下:

{
	"user_info":{
		"name":"思無邪",
		"address":"桃花島水簾洞123号",
		"phone":"15960238696"
	},
	"goods_list":[
		{
			"goods_name":"Mate30",
			"goods_number":1,
			"goods_price":8888
		},
		{
			"goods_name":"格力中央空調",
			"goods_number":1,
			"goods_price":58000
		},
		{
			"goods_name":"紅蜻蜓皮鞋",
			"goods_number":3,
			"goods_price":999
		}
	]
}
           

從以上json串的内容可以梳理出它的基本格式定義,詳細說明如下:

1、整個json串由一對花括号包裹,并且内部的每個結構都以花括号包起來;

2、參數格式類似鍵值對,其中鍵名與鍵值之間以冒号分隔,形如“鍵名:鍵值”;

3、兩個鍵值對之間以逗号分隔;

4、鍵名需要用雙引号括起來,鍵值為數字的話則無需雙引号,為字元串的話仍需雙引号;

5、json數組通過方括号表達,方括号内部依次羅列各個元素,具體格式形如“數組的鍵名:[元素1,元素2,元素3]”;

由此可見,JSON串的格式定義很簡潔,層次結構也很清晰。使用FastJson解析json串更是友善,首先調用JSONObject的parseObject方法,得到某個json串的JSONObject對象,示例代碼如下:

// 根據json串獲得JSONObject對象
JSONObject object = JSONObject.parseObject(json);
           

接着就能對JSONObject對象開展進一步的操作,主要的處理方法說明如下:

getString:擷取指定鍵名的字元串。

getIntValue:擷取指定鍵名的整型數。

getDoubleValue:擷取指定鍵名的雙精度數。

getBooleanValue:擷取指定鍵名的布爾值。

getJSONObject:擷取指定鍵名的JSONObject對象。

getJSONArray:擷取指定鍵名的JSONArray數組。注意JSONArray類型派生自清單List,意味着可以把它當作清單一樣讀寫。

put:添加指定的鍵值對資訊。

remove:移除指定鍵名的鍵值對。

clear:清空目前的JSONObject對象。

toJSONString:把JSONObject對象轉換為字元串。

針對前述的購物訂單json串,為了有效地儲存解析後的訂單資訊,有必要定義幾個相應的實體類。比如要定義一個使用者資訊類,該類的定義代碼如下所示:

//定義一個使用者資訊
public class UserInfo {
	public String name; // 使用者姓名
	public String address; // 收貨位址
	public String phone; // 聯系号碼
}
           

再定義一個商品項資訊類,該類的定義代碼如下所示:

//定義一項商品資訊
public class GoodsItem {
	public String goods_name; // 商品名稱
	public int goods_number; // 商品數量
	public double goods_price; // 商品價格
}
           

最後定義外層的購物訂單資訊類,該類的定義代碼如下所示:

//定義一次購物訂單資訊
public class GoodsOrder {
	// 使用者資訊
	public UserInfo user_info = new UserInfo();
	// 購買的商品清單
	public List<GoodsItem> goods_list = new ArrayList<GoodsItem>();
}
           

定義好了這些實體類,即可将JSONObject對象中的各個資料解析并填入購物訂單對象,完整的json解析代碼示例如下:

// 把json字元串解析到對應的實體對象
private static GoodsOrder testParserJson(String json) {
	// 建立一個購物訂單對象
	GoodsOrder order = new GoodsOrder();
	// 根據json串獲得JSONObject對象
	JSONObject object = JSONObject.parseObject(json);
	// 從JSONObject對象中擷取鍵名為user_info的使用者資訊json對象
	JSONObject user_info = object.getJSONObject("user_info");
	// 從使用者資訊json對象中擷取鍵名為name的字元串
	order.user_info.name = user_info.getString("name");
	// 從使用者資訊json對象中擷取鍵名為address的字元串
	order.user_info.address = user_info.getString("address");
	// 從使用者資訊json對象中擷取鍵名為phone的字元串
	order.user_info.phone = user_info.getString("phone");
	System.out.println(String.format("使用者資訊如下:姓名=%s,位址=%s,手機号=%s", 
			order.user_info.name, order.user_info.address, order.user_info.phone));
	// 從JSONObject對象中擷取鍵名為goods_list的商品資訊json數組
	JSONArray goods_list = object.getJSONArray("goods_list");
	for (int i=0; i<goods_list.size(); i++) { // 周遊商品資訊數組
		GoodsItem item = new GoodsItem(); // 建立一項商品對象
		// 從json數組擷取下标為i的商品json對象
		JSONObject goods_item = (JSONObject) goods_list.get(i);
		// 從商品json對象中擷取鍵名為goods_name的字元串
		item.goods_name = goods_item.getString("goods_name");
		// 從商品json對象中擷取鍵名為goods_number的整型數
		item.goods_number = goods_item.getIntValue("goods_number");
		// 從商品json對象中擷取鍵名為goods_price的雙精度數
		item.goods_price = goods_item.getDoubleValue("goods_price");
		System.out.println(String.format("第%d個商品:名稱=%s,數量=%d,價格=%f", 
				i+1, item.goods_name, item.goods_number, item.goods_price));
		order.goods_list.add(item); // 往商品清單中添加指定商品對象
	}
	return order; // 傳回解析後的購物訂單對象
}
           

運作上述的解析代碼,觀察到以下的購物訂單日志,可見成功實作了json串到對象的解析操作:

使用者資訊如下:姓名=思無邪,位址=桃花島水簾洞123号,手機号=15960238696
第1個商品:名稱=Mate30,數量=1,價格=8888.000000
第2個商品:名稱=格力中央空調,數量=1,價格=58000.000000
第3個商品:名稱=紅蜻蜓皮鞋,數量=3,價格=999.000000
           

注意到商品訂單json串跟GoodsOrder定義的資料結構一一對應,不管是參數名稱還是參數類型全部吻合,如此一來就能運用FastJson的自動轉換絕技,整個自動轉換隻有兩次代碼調用:第一次調用JSONObject的parseObject方法,獲得json串對應的JSONObject對象;第二次調用JSONObject的toJavaObject方法,依次填寫上一步驟的JSONObject對象,以及待轉換的實體類型如GoodsOrder.class。下面便是将json串自動轉換成實體對象的代碼例子:

// 根據json串獲得JSONObject對象
JSONObject object = JSONObject.parseObject(json);
// 把JSONObject對象中的資訊一一轉成購物訂單資訊
GoodsOrder order = (GoodsOrder) JSONObject.toJavaObject(object, GoodsOrder.class);
           

哇噻,這個自動轉換功能不要太好用喲,實乃開發者的一大福音。反過來,把某個實體對象轉換成對應的json串,也隻需短短一行代碼就搞定了,調用JSONObject的toJSONString方法即可,具體轉換代碼示例如下:

// 把購物訂單對象轉換成json字元串
String json = JSONObject.toJSONString(order);
           

當然,有時候并不需要把整個實體對象都轉換為json串,而是提取該對象的部分資訊再封裝成json串,這樣的話,還是按照慣例逐漸往json串添加鍵值對資訊,也就是需要封裝的資料才要put進JSONObject對象。下面是根據購物訂單對象逐漸生成json串的代碼例子:

// 根據購物訂單對象逐漸拼接生成json字元串
private static String testGenerateJson(GoodsOrder order) {
	// 建立一個準備儲存購物訂單的JSONObject對象
	JSONObject object = new JSONObject();
	// 建立一個準備儲存使用者資訊的JSONObject對象
	JSONObject user_info = new JSONObject();
	// 往使用者資訊json對象中添加鍵名為name的姓名資訊
	user_info.put("name", order.user_info.name);
	// 往使用者資訊json對象中添加鍵名為address的位址資訊
	user_info.put("address", order.user_info.address);
	// 往使用者資訊json對象中添加鍵名為phone的号碼資訊
	user_info.put("phone", order.user_info.phone);
	// 往購物訂單json對象中添加鍵名為user_info的使用者資訊
	object.put("user_info", user_info);
	// 建立一個準備儲存商品項的JSONArray數組
	JSONArray goods_list = new JSONArray();
	// 周遊購物訂單裡的各項商品
	for (GoodsItem item : order.goods_list) {
		// 建立一個準備儲存商品資訊的JSONObject對象
		JSONObject goods_item = new JSONObject();
		// 往商品資訊json對象中添加鍵名為goods_name的名稱資訊
		goods_item.put("goods_name", item.goods_name);
		// 往商品資訊json對象中添加鍵名為goods_number的數量資訊
		goods_item.put("goods_number", item.goods_number);
		// 往商品資訊json對象中添加鍵名為goods_price的價格資訊
		goods_item.put("goods_price", item.goods_price);
		goods_list.add(item); // 往json數組中添加JSONObject對象
	}
	// 往購物訂單json對象中添加鍵名為goods_list的商品項資訊
	object.put("goods_list", goods_list);
	return object.toJSONString(); // 把JSONObject對象轉換為json字元串
}
           

更多Java技術文章參見《Java開發筆記(序)章節目錄》