蜜果私塾:JSON知識總結(jié)入門篇
記錄人:阿蜜果
日期:2010-9-25
1. 何謂JSON
JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式。易于人閱讀和編寫,同時也易于機(jī)器解析和生成。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON采用完全獨立于語言的文本格式,但是也使用了類似于C語言家族的習(xí)慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的數(shù)據(jù)交換語言。
JSON具有如下具體形式:
1)JSON是一個無序的“名稱/值”對的集合。一個對象以“{”開始,“}”結(jié)束,每個名稱后跟一個“:”號,“名稱/值”對之間使用“,”分隔;
2)數(shù)組是值(value)的有序集合。一個數(shù)組以“[”(左中括號)開始,“]”(右中括號)結(jié)束。值之間使用“,”(逗號)分隔;
3)值(value)可以是雙引號括起來的字符串(string)、數(shù)值(number)、true、false、 null、對象(object)或者數(shù)組(array)。這些結(jié)構(gòu)可以嵌套;
4)字符串(string)是由雙引號包圍的任意數(shù)量Unicode字符的集合,使用反斜線轉(zhuǎn)義。一個字符(character)即一個單獨的字符串(character string)。字符串(string)與C或者Java的字符串非常相似;
5)數(shù)值(number)也與C或者Java的數(shù)值非常相似。除去未曾使用的八進(jìn)制與十六進(jìn)制格式。除去一些編碼細(xì)節(jié)。
2. JSON與XML的比較
從如下部分進(jìn)行比較:
1)可讀性:JSON比XML的可讀性稍微差點,相比來說XML更結(jié)構(gòu)化。一邊是簡易的語法,一邊是規(guī)范的標(biāo)簽形式;
2) 可擴(kuò)展性:XML天生有很好的擴(kuò)展性,JSON當(dāng)然也有,沒有什么是XML能擴(kuò)展,JSON不能的。不過JSON在Javascript主場作戰(zhàn),可以存儲Javascript復(fù)合對象,有著xml不可比擬的優(yōu)勢;
3) 編碼難度:XML有豐富的編碼工具,比如Dom4j、JDom等,JSON也有提供的工具。無工具的情況下,相信熟練的開發(fā)人員一樣能很快的寫出想要的xml文檔和JSON字符串,不過,xml文檔要多很多結(jié)構(gòu)上的字符;
4)解碼難度
XML的解析方式有兩種:一是通過文檔模型解析,也就是通過父標(biāo)簽索引出一組標(biāo)記。例如:xmlData.getElementsByTagName("tagName"),但是這樣是要在預(yù)先知道文檔結(jié)構(gòu)的情況下使用,無法進(jìn)行通用的封裝。
另外一種方法是遍歷節(jié)點(document 以及 childNodes)。這個可以通過遞歸來實現(xiàn),不過解析出來的數(shù)據(jù)仍舊是形式各異,往往也不能滿足預(yù)先的要求。
凡是這樣可擴(kuò)展的結(jié)構(gòu)數(shù)據(jù)解析起來一定都很困難。
如果預(yù)先知道JSON結(jié)構(gòu)的情況下,使用JSON非常簡單。純粹的前臺開發(fā)人員,一定會非常喜歡JSON。但是如果你是一個應(yīng)用開發(fā)人員,就不是那么喜歡了,畢竟xml才是真正的結(jié)構(gòu)化標(biāo)記語言,用于進(jìn)行數(shù)據(jù)傳遞。而如果不知道JSON的結(jié)構(gòu)而去解析JSON的話,那就非常費(fèi)勁。
在Javascript地盤內(nèi),JSON畢竟是主場作戰(zhàn),其優(yōu)勢當(dāng)然要遠(yuǎn)遠(yuǎn)優(yōu)越于xml。如果JSON中存儲Javascript復(fù)合對象,而且不知道其結(jié)構(gòu)的話,我相信很多程序員也一樣是哭著解析JSON的。
3. 簡單實例
3.1從文本中取得JSON字符串
3.1.1 功能描述
在下面的實例中json.html通過ajax獲得json.txt中的JSON字符串的內(nèi)容,并在json.html對結(jié)果進(jìn)行解析后進(jìn)行展示。
3.1.2 JSON字符串文件:json.txt
如果json.txt文件中的json字符串為:


{
"programmers": [

{ "firstName": "阿蜜果", "lastName":"McLaughlin", "email": "brett@newInstance.com" },

{ "firstName": "范范", "lastName":"Hunter", "email": "jason@servlets.com" },

{ "firstName": "高子", "lastName":"Harold", "email": "elharo@macfaq.com" }
],
"authors": [

{ "firstName": "安安", "lastName": "Asimov", "genre": "science fiction" },


{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },


{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }
],
"musicians": [

{ "firstName": "茂茂", "lastName": "Clapton", "instrument": "guitar" },


{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
]
}
例如如果想獲得第一個程序員的firstName,可通過如下語句:
var result = xmlHttp.responseText;
var json = eval("(" + result + ")");
alert(json.programmers[0].firstName);
第二個authors的genre可通過如下語句獲得:
json.authors[0].genre
3.1.2 JSON字符串讀取和解析文件:json.html
將如上的json.txt保存為UTF-8的文件,編輯json.html文件,內(nèi)容參考如下:
<html>
<head>
<title>JsonTest</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<script type="text/javascript">
var xmlHttp;
function createXMLHttpRequest()

{
if(window.ActiveXObject)

{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest)

{
xmlHttp = new XMLHttpRequest();
}
}

function startRequest()

{
createXMLHttpRequest();
try

{
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", "json.txt", true);
xmlHttp.send(null);
}
catch(exception)

{
alert("xmlHttp Fail");
}
}

function handleStateChange()

{
if(xmlHttp.readyState == 4)

{
if (xmlHttp.status == 200 || xmlHttp.status == 0)

{
var result = xmlHttp.responseText;
var json = eval("(" + result + ")");
alert(json.programmers[0].firstName + ',' + json.programmers[0].lastName + ',' + json.programmers[0].email);
alert(json.programmers[1].firstName + ',' + json.programmers[1].lastName + ',' + json.programmers[1].email);
alert(json.programmers[2].firstName + ',' + json.programmers[2].lastName + ',' + json.programmers[2].email);

alert(json.authors[0].firstName + ',' + json.authors[0].lastName + ',' + json.authors[0].genre);
alert(json.authors[1].firstName + ',' + json.authors[1].lastName + ',' + json.authors[1].genre);
alert(json.authors[2].firstName + ',' + json.authors[2].lastName + ',' + json.authors[2].genre);

alert(json.musicians[0].firstName + ',' + json.musicians[0].lastName + ',' + json.musicians[0].instrument);
alert(json.musicians[1].firstName + ',' + json.musicians[1].lastName + ',' + json.musicians[1].instrument);
}
}
}
</script>
</head>
<body>
<div>
<input type="button" value="JSON Test" onclick="startRequest();" />
</div>
</body>
</html>

在ajax的回調(diào)函數(shù)handleStateChange中,讀者可對照json.txt文件重點關(guān)注下json字符串的取值方法。
3.2將Java對象轉(zhuǎn)換為JSON字符串
3.2.1 功能描述
在該實例中,講述如何將Java構(gòu)造的復(fù)雜對象轉(zhuǎn)換為JSON字符串,Pagination對象中包含int類型的pageNo屬性,還包括List列表類型的result。List中包括的又是Book類型的對象,Book對象包括簡單類型的屬性id和name,也包括List對象authors,表示該書的多個作者信息。authors列表的對象包含id和name屬性。
我們構(gòu)造一個Pagination類型的分頁對象,它包含兩本書Book對象,分別為《人生若只如初見》和《海邊的卡夫卡》,并設(shè)置了它們的作者等信息。
3.2.2 建立工程,并將包引入
在Eclipse中建立一個jsonStudy的Java工程或Java Web工程,在src目錄下建立com.amigo.json包,用來放置本示例的Java代碼。
另外轉(zhuǎn)換時需要用到一些包,需要將其放到lib目錄下,所需的包如下圖所示:

commons系列的包,可在網(wǎng)站:http://www.docjar.com/上面搜索下載,其它包可下載網(wǎng)站如下:
json-lib-2.2-jdk15.jar:http://json-lib.sourceforge.net/
ezmorph.jar: http://ezmorph.sourceforge.net/
morph-1.0.1.jar: http://morph.sourceforge.net/
3.2.3 JavaBean對象
Author類:
package com.amigo.json;


public class Author
{
private String id;

private String name;

// 省略getter/setter方法
}
Book類:
package com.amigo.json;

import java.util.List;


public class Book
{
private String id;

private String name;

private List<Author> authors;

// 省略getter/setter方法
}
Pagination類:
package com.amigo.json;

import java.util.List;


public class Pagination
{
private int pageNo;

private List<Object> results;

// 省略getter/setter方法
}
3.2.4 測試類
JsonTest測試類:
package com.amigo.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;


public class JsonTest
{

/** *//**
* @param args
*/

public static void main(String[] args)
{
// 當(dāng)是對象的時候
Author author = new Author();
author.setId("1");
author.setName("張三");
JSONObject jsonObject = JSONObject.fromObject(author);
System.out.println(jsonObject);

// 當(dāng)是數(shù)組或list的時候
Author[] authors = new Author[5];
List<Author> authorsList = new ArrayList<Author>();

for (int i = 0; i < authors.length; i++)
{
authors[i] = new Author();
authors[i].setId(String.valueOf(i + 1));
authors[i].setName("張三" + (i + 1));
// 添加到list
authorsList.add(authors[i]);
}
JSONArray jsonArray = JSONArray.fromObject(authorsList);
System.out.println(jsonArray);

jsonArray = JSONArray.fromObject(authors);
System.out.println(jsonArray);

// 復(fù)雜結(jié)構(gòu)構(gòu)造
Map<String,Object> map = new HashMap<String,Object>();
Pagination pagination = new Pagination();
pagination.setPageNo(1);
pagination.setResults(new ArrayList<Object>());

// 構(gòu)造第一個book的信息
Book book = new Book();
book.setId("1");
book.setName("人生若只如初見");
book.setAuthors(new ArrayList<Author>());
pagination.getResults().add(book);

author = new Author();
author.setId("1");
author.setName("張三");
book.getAuthors().add(author);
author = new Author();
author.setId("2");
author.setName("李四");
book.getAuthors().add(author);

// 構(gòu)造第二個book的信息
Book book2 = new Book();
book2.setId("2");
book2.setName("海邊的卡夫卡");
book2.setAuthors(new ArrayList<Author>());
author = new Author();
author.setId("1");
author.setName("村上春樹");
book2.getAuthors().add(author);
pagination.getResults().add(book2);

map.put("page", pagination);

JSONObject jsonObjectFromMap = JSONObject.fromObject(map);
System.out.println(jsonObjectFromMap);
}
}
如上測試類展示了如何使用所引包里面的方法來將Java簡單對象、列表、數(shù)組和復(fù)雜的Map對象轉(zhuǎn)換為JSON字符串的方法。
3.2.5 運(yùn)行結(jié)果
運(yùn)行JsonText.java,運(yùn)行結(jié)果如下:


{"id":"1","name":"張三"}


[
{"id":"1","name":"張三1"},
{"id":"2","name":"張三2"},
{"id":"3","name":"張三3"},
{"id":"4","name":"張三4"},
{"id":"5","name":"張三5"}]


[
{"id":"1","name":"張三1"},
{"id":"2","name":"張三2"},
{"id":"3","name":"張三3"},
{"id":"4","name":"張三4"},
{"id":"5","name":"張三5"}]



{"page":
{"pageNo":1,"results":[
{"authors":[
{"id":"1","name":"張三"},
{"id":"2","name":"李四"}],"id":"1","name":"人生若只如初見"},
{"authors":[
{"id":"1","name":"村上春樹"}],"id":"2","name":"海邊的卡夫卡"}]}}

該實例Map復(fù)合結(jié)構(gòu)的格式化的JSON字符串為:


{
"page":

{"pageNo":1,
"results":

[
{
"authors":
[

{"id":"1", "name":"張三"},

{"id":"2", "name":"李四"}
],
"id":"1",
"name":"人生若只如初見"
},

{
"authors":
[

{"id":"1","name":"村上春樹"}
],
"id":"2",
"name":"海邊的卡夫卡"
}]
}
}
有興趣的讀者可將該字符串拷貝到上面實例的json.txt文件中,并稍微修改下json.html對內(nèi)容進(jìn)行輸出。
4. 常見問題
4.1中文亂碼問題說明
在3.1的實例中,為了避免中文亂碼問題,需要注意以下兩點:
1)在json.html中添加如下一句:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
2)使用UE等保存json.txt文件時,需要將其保存為UTF-8模式。
在3.2的實例中,當(dāng)筆者沒有將ezmorph.jar、morph-1.0.1.jar包導(dǎo)入時,雖然類都沒有報錯,但是運(yùn)行時拋出java.lang.NoClassDefFoundError:net/sf/ezmorph/Morpher異常,如果讀者也出現(xiàn)該異常,需要將這沒有加入的包加入到工程中。
5. 參考文檔
《JSON_百度百科》:http://baike.baidu.com/view/136475.htm
《一個處理JSON的例子,帶演示》:http://bbs.blueidea.com/thread-2790525-1-1.html
《JSON實例》:http://hi.baidu.com/northarcher/blog/item/05d7fa1fca9c9ec3a786699f.html
《JSON中,java.lang.NoClassDefFoundError:net/sf/ezmorph/Morpher異常解決》:http://minner.javaeye.com/blog/428802
posted on 2010-09-25 15:23
阿蜜果 閱讀(4466)
評論(0) 編輯 收藏 所屬分類:
Ajax