JSON的序列化與反序列化及其在前後臺互動中的應用
1、什麼是JSON
JSON是JavaScript Object Notation的縮寫,它是一種資料交換格式。
在JSON出現之前,大家一直用XML來傳遞資料。因為XML是一種純文字格式,所以它適合在網路上交換資料。XML本身不算複雜,但是,加上DTD、XSD、XPath、XSLT等一大堆複雜的規範以後,任何正常的軟體開發人員碰到XML都會感覺頭大了,最後大家發現,即使你努力鑽研幾個月,也未必搞得清楚XML的規範。
終於,在2002年的一天,道格拉斯·克羅克福特(Douglas Crockford)同學為了拯救深陷水深火熱同時又被某幾個巨型軟體企業長期愚弄的軟體工程師,發明了JSON這種超輕量級的資料交換格式。
道格拉斯同學長期擔任雅虎的高階架構師,自然鍾情於JavaScript。他設計的JSON實際上是JavaScript的一個子集。在JSON中,一共就這麼幾種資料型別:
- number:和JavaScript的number完全一致;<br>
- boolean:就是JavaScript的true或false;
- string:就是JavaScript的string;
- null:就是JavaScript的null;
- array:就是JavaScript的Array表示方式——[];
- object:就是JavaScript的{...}表示方式。
以及上面的任意組合。
並且,JSON還定死了字符集必須是UTF-8,表示多語言就沒有問題了。為了統一解析,JSON的字串規定必須用雙引號”“,Object的鍵也必須用雙引號”“。
由於JSON非常簡單,很快就風靡Web世界,並且成為ECMA標準。幾乎所有程式語言都有解析JSON的庫,而在JavaScript中,我們可以直接使用JSON,因為JavaScript內建了JSON的解析。
把任何JavaScript物件變成JSON,就是把這個物件序列化成一個JSON格式的字串,這樣才能夠通過網路傳遞給其他計算機。如果我們收到一個JSON格式的字串,只需要把它反序列化成一個JavaScript物件,就可以在JavaScript中直接使用這個物件了
2、JSON序列化
讓我們先把小明這個物件序列化成JSON格式的字串:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};
JSON.stringify(xiaoming);
在chrome瀏覽器的console中執行上面程式碼,輸出結果如下:
"{"name":"小明","age":14,"gender":true,"height":1.65,"grade":null,"middle-school":"\"W3C\" Middle School","skills":["JavaScript","Java","Python","Lisp"]}"
要輸出得好看一些,可以加上引數,按縮排輸出:
JSON.stringify(xiaoming, null, ' ');
結果:
"{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}"
第二個引數用於控制如何篩選物件的鍵值,如果我們只想輸出指定的屬性,可以傳入Array:
JSON.stringify(xiaoming, ['name', 'skills'], ' ');
結果:
"{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}"
還可以傳入一個函式,這樣物件的每個鍵值對都會被函式先處理:
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringify(xiaoming, convert, ' ');
結果:
"{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle-school": "\"W3C\" MIDDLE SCHOOL",
"skills": [
"JAVASCRIPT",
"JAVA",
"PYTHON",
"LISP"
]
}"
如果我們還想要精確控制如何序列化小明,可以給xiaoming定義一個toJSON()的方法,直接返回JSON應該序列化的資料:
var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '\"W3C\" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只輸出name和age,並且改變了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'
3、JSON反序列化
拿到一個JSON格式的字串,我們直接用JSON.parse()把它變成一個JavaScript物件:
JSON.parse('[1,2,3,true]'); // Array [1, 2, 3, true]
JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}
JSON.parse('true'); // true
JSON.parse('123.45'); // 123.45
//還可以接收一個函式,用來轉換解析出的屬性:
JSON.parse('{"name":"小明","age":14}', function (key, value) {
// 把number * 2:
if (key === 'name') {
return value + '同學';
}
return value;
}); // Object {name: '小明同學', age: 14}
在JavaScript中使用JSON,就是這麼簡單!
4、JSON物件與JSON字串
在資料傳輸流程中,json是以文字,即字串的形式傳遞的,而JS操作的是JSON物件,所以,JSON物件和JSON字串之間的相互轉換是關鍵。
JSON物件是直接可以使用JQuery操作的格式,和js中的物件一樣,可以用物件(類名)點出屬性(方法)。JSON字串僅僅只是一個字串,一個整體,不擷取的話沒辦法取出其中儲存的資料,不能直接使用,除非你只想alert()它。
JSON字串:
var str1 = '{ "name": "haorooms", "sex": "man" }';
JSON物件:
var str2 = { "name": "haorooms", "sex": "man" };
讀取JSON物件的屬性值:
var str2 = { "name": "haorooms", "sex": "man" };
alert(str2.name);
//彈出” haorooms”
//對於複雜一點的JSON物件
var str={"GetUserPostByIdResult":{"Age":"33","ID":"2server","Name":"haorooms"}};
alert(str.GetUserPostByIdResult.Name); //彈出haorooms
對於JSON字串,如果想像上面那樣自如的讀取其屬性,必須運用下面的方法將JSON字串領先轉化為JSON物件(這一點在ajax返回的時候,經常遇到!):
var str = '{ "name": "haorooms", "sex": "man" }';
//方法1
var obj1 = eval('(' + str + ')'); //Object {name: "haorooms", sex: "man"}
//方法2
var obj2 = JSON.parse(str); //Object {name: "haorooms", sex: "man"}
5、JSON實現後臺與前端的互動
作為後臺人員,與資料庫互動、處理業務邏輯已經駕輕就熟,但與前端合作就顯得不是那麼熟練了。舉一個例子,一個使用者列表,我們從資料庫取出來是一個List<User>,但它在前端顯示就是一個很炫酷的使用者列表,我們後臺人員是需要把資料以表格樣式呈現然後讓前端人員去加樣式呢,還是前端做好樣式留出介面由後臺人員給出資料呢?
剛剛接觸網站開發可能都會出現類似的問題,我們是多希望前端和後臺的工作分的清清楚楚啊!其實不用想那麼複雜,JSON就可以幫我們!後臺只需告訴前端,請求某一個URL地址就可以得到使用者資料的JSON格式的資料,前端在需要的時候自己去請求就好,剩下的工作就由前端做就好了,清楚乾淨!
程式碼例項:
/**
* 測試獲取所有使用者列表
* @param request
* @return String
* @throws IOException
*/
@RequestMapping("/getAllUserTest")
public String getAllUserTest(HttpServletRequest request, HttpServletResponse response) throws IOException {
//從資料庫中取出所有使用者資訊,返回值為一個User物件集合,每個User物件包含username與age兩個引數
List<User> findAll = userService.findAll();
//建立JSONArray例項
JSONArray jsonArray = new JSONArray();
//for each迴圈取出每個User物件
for(User user: findAll) {
//JSONObject是一個{}包裹起來的一個物件(Object),
//JSONArray則是[]包裹起來的一個數組(Array)
//此處為物件,所以用得到JSONObject
JSONObject jo = new JSONObject();
jo.put("username", user.getUsername());
jo.put("age", user.getAge());
jsonArray.add(jo);
}
try {
//後臺輸出測試
System.out.println(jsonArray.toString());
//設定字符集
response.setCharacterEncoding("UTF-8");
//頁面輸出
response.getWriter().println("JSON輸出形式:");
response.getWriter().write(jsonArray.toString());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
那麼前端請求相應的URL就可以得到所有的使用者資訊了!效果如下:
前臺的資料如何通過JSON這種資料交換格式傳入後臺?
(1)將要傳入後臺的資料組裝成JSON格式的字串
var data = [{'name':'jim' , 'age':20} , {'name':'king' , 'age':26},{'name':'jge' , 'age':30}];
var jsonString = JSON.stringify(data);
(2)使用jQuery的ajax請求向後臺傳資料
$.ajax({
type: "post",
url: url,
dataType : 'json',
data : {'mydata':jsonString},
success: function(data,textStatus){
alert("操作成功");
},
error: function(xhr,status,errMsg){
alert("操作失敗!");
}
});
(3)後臺接收資料並解析
String jsonString = ServletActionContext.getRequest().getParameter("mydata");
JSONArray jsonArray = JSONArray.fromObject(jsonString);
for(int i = 0;i < jsonArray.length(); i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i);
jsonObj.getInt("name");
jsonObj.getString("age");
}