# 概念
JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式蝶怔。 易于閱讀和編寫。同時也易于機(jī)器解析和生成城看。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一個子集螟蒸。 JSON采用完全獨(dú)立于語言的文本格式,但是也使用了類似于C語言家族的習(xí)慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)餐屎。 這些特性使JSON成為理想的數(shù)據(jù)交換語言。
# JSON的結(jié)構(gòu)
JSON由如下兩種結(jié)構(gòu)建構(gòu):
- “名稱/值”對的集合(A collection of name/value pairs)玩祟。不同的語言中,它被理解為對象(object)屿聋,紀(jì)錄(record)空扎,結(jié)構(gòu)(struct),字典(dictionary)润讥,哈希表(hash table)转锈,有鍵列表(keyed list),或者關(guān)聯(lián)數(shù)組 (associative array)楚殿。
- 值的有序列表(An ordered list of values)撮慨。在大部分語言中,它被理解為數(shù)組(array)脆粥。
這些都是常見的數(shù)據(jù)結(jié)構(gòu)砌溺。事實(shí)上大部分現(xiàn)代計(jì)算機(jī)語言都以某種形式支持它們。這使得一種數(shù)據(jù)格式在同樣基于這些結(jié)構(gòu)的編程語言之間交換成為可能变隔。
JSON具有以下這些表現(xiàn)形式
-
對象(JSONObject):
對象是一個無序的“‘名稱/值’對”集合规伐。一個對象以“{”(左括號)開始,“}”(右括號)結(jié)束匣缘。每個“名稱”后跟一個“:”(冒號)猖闪;“‘名稱/值’ 對”之間使用“,”(逗號)分隔鲜棠。
-
數(shù)組(JSONArray):
數(shù)組是值(value)的有序集合。一個數(shù)組以“[”(左中括號)開始培慌,“]”(右中括號)結(jié)束豁陆。值之間使用“,”(逗號)分隔。
-
值
值(value)可以是雙引號括起來的字符串(string)吵护、數(shù)值(number)盒音、true、false何址、 null里逆、對象(object)或者數(shù)組(array)。這些結(jié)構(gòu)可以嵌套用爪。
-
字符串
字符串(string)是由雙引號包圍的任意數(shù)量Unicode字符的集合原押,使用反斜線轉(zhuǎn)義。一個字符(character)即一個單獨(dú)的字符串(character string)偎血。
字符串(string)與C或者Java的字符串非常相似诸衔。
-
數(shù)值
數(shù)值(number)也與C或者Java的數(shù)值非常相似。除去未曾使用的八進(jìn)制與十六進(jìn)制格式颇玷。除去一些編碼細(xì)節(jié)笨农。
空白可以加入到任何符號之間。
JSON在Android中的使用
- android2.3提供的son解析類
android的json解析部分都在包org.json下帖渠,主要有以下幾個類:
JSONObject:可以看作是一個json對象
JSONStringer:json文本構(gòu)建類
JSONArray:可以看作是json的數(shù)組
JSONTokener:son解析類
JSONException:json中用到的異常
- JSONObject, JSONArray來構(gòu)建json文本
// 假設(shè)現(xiàn)在要創(chuàng)建這樣一個json文本
// {
// "phone" : ["12345678", "87654321"], // 數(shù)組
// "name" : "yuanzhifei89", // 字符串
// "age" : 100, // 數(shù)值
// "address" : { "country" : "china", "province" : "jiangsu" }, // 對象
// "married" : false // 布爾值
// }
try {
// 首先最外層是{}谒亦,是創(chuàng)建一個對象
JSONObject person = new JSONObject();
// 第一個鍵phone的值是數(shù)組,所以需要創(chuàng)建數(shù)組對象
JSONArray phone = new JSONArray();
phone.put("12345678").put("87654321");
person.put("phone", phone);
person.put("name", "yuanzhifei89");
person.put("age", 100);
// 鍵address的值是對象空郊,所以又要創(chuàng)建一個對象
JSONObject address = new JSONObject();
address.put("country", "china");
address.put("province", "jiangsu");
person.put("address", address);
person.put("married", false);
} catch (JSONException ex) {
// 鍵為null或使用json不支持的數(shù)字格式(NaN, infinities)
throw new RuntimeException(ex);
}
- getType和optType api的使用
getType可以將要獲取的鍵的值轉(zhuǎn)換為指定的類型份招,如果無法轉(zhuǎn)換或沒有值則拋出JSONException
optType也是將要獲取的鍵的值轉(zhuǎn)換為指定的類型,無法轉(zhuǎn)換或沒有值時返回用戶提供或這默認(rèn)提供的值
try {
// 所有使用的對象都是用上面創(chuàng)建的對象
// 將第一個電話號碼轉(zhuǎn)換為數(shù)值和將名字轉(zhuǎn)換為數(shù)值
phone.getLong(0);
person.getLong("name"); // 會拋異常狞甚,因?yàn)槊譄o法轉(zhuǎn)換為long
phone.optLong(0); // 代碼內(nèi)置的默認(rèn)值
phone.optLong(0, 1000); // 用戶提供的默認(rèn)值
person.optLong("name");
person.optLong("name", 1000); // 不像上面那樣拋異常锁摔,而是返回1000
} catch (JSONException ex) {
// 異常處理代碼
}
- 除了上面的兩個類,還可以使用JSONStringer來構(gòu)建json文本
try {
JSONStringer jsonText = new JSONStringer();
// 首先是{哼审,對象開始谐腰。object和endObject必須配對使用
jsonText.object();
jsonText.key("phone");
// 鍵phone的值是數(shù)組。array和endArray必須配對使用
jsonText.array();
jsonText.value("12345678").value("87654321");
jsonText.endArray();
jsonText.key("name");
jsonText.value("yuanzhifei89");
jsonText.key("age");
jsonText.value(100);
jsonText.key("address");
// 鍵address的值是對象
jsonText.object();
jsonText.key("country");
jsonText.value("china");
jsonText.key("province");
jsonText.value("jiangsu");
jsonText.endObject();
jsonText.key("married");
jsonText.value(false);
// }涩盾,對象結(jié)束
jsonText.endObject();
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
- json文本解析類JSONTokener
按照RFC4627規(guī)范將json文本解析為相應(yīng)的對象十气。
對于將json文本解析為對象,只需要用到該類的兩個api:
構(gòu)造方法 與 public Object nextValue();
// {
// "phone" : ["12345678", "87654321"], // 數(shù)組
// "name" : "yuanzhifei89", // 字符串
// "age" : 100, // 數(shù)值
// "address" : { "country" : "china", "province" : "jiangsu" }, // 對象
// "married" : false // 布爾值
// }
private static final String JSON =
"{" +
" \"phone\" : [\"12345678\", \"87654321\"]," +
" \"name\" : \"yuanzhifei89\"," +
" \"age\" : 100," +
" \"address\" : { \"country\" : \"china\", \"province\" : \"jiangsu\" }," +
" \"married\" : false," +
"}";
try {
JSONTokener jsonParser = new JSONTokener(JSON);
// 此時還未讀取任何json文本春霍,直接讀取就是一個JSONObject對象桦踊。
// 如果此時的讀取位置在"name" : 了,那么nextValue就是"yuanzhifei89"(String)
JSONObject person = (JSONObject) jsonParser.nextValue();
// 接下來的就是JSON對象的操作了
person.getJSONArray("phone");
person.getString("name");
person.getInt("age");
person.getJSONObject("address");
person.getBoolean("married");
} catch (JSONException ex) {
// 異常處理代碼
}
其它的api基本就是用來查看json文本中的文本的
try {
JSONTokener jsonParser = new JSONTokener(JSON);
// 繼續(xù)向下讀8個json文本中的字符终畅。此時剛開始籍胯,即在{處
jsonParser.next(8); //{ "phone竟闪。tab算一個字符
// 繼續(xù)向下讀1個json文本中的字符
jsonParser.next(); //"
// 繼續(xù)向下讀取一個json文本中的字符。該字符不是空白杖狼、同時也不是注視中的字符
jsonParser.nextClean(); //:
// 返回當(dāng)前的讀取位置到第一次遇到'a'之間的字符串(不包括a)炼蛤。
jsonParser.nextString('a'); // ["12345678", "87654321"], "n(前面有兩個空格)
// 返回當(dāng)前讀取位置到第一次遇到字符串中(如"0089")任意字符之間的字符串,同時該字符是trimmed的蝶涩。(此處就是第一次遇到了89)
jsonParser.nextTo("0089"); //me" : "yuanzhifei
// 讀取位置撤銷一個
jsonParser.back();
jsonParser.next();
// 讀取位置前進(jìn)到指定字符串處(包括字符串)
jsonParser.skipPast("address");
jsonParser.next(8); //" : { "c
// 讀取位置前進(jìn)到執(zhí)行字符處(不包括字符)
jsonParser.skipTo('m');
jsonParser.next(8); //married"
} catch (JSONException ex) {
// 異常處理代碼
}
- json中的null和java中的null
// json對象的成員為null可能有兩種情況:
// 1: 不出現(xiàn)該成員的名稱(對應(yīng)java中的null)
// 2: 成員值為null理朋。(對應(yīng)java中的JSONObject.NULL)
// 完整的Json
// {
// "phone" : ["12345678", "87654321"], // 數(shù)組
// "name" : "yuanzhifei89", // 字符串
// "age" : 100, // 數(shù)值
// "address" : { "country" : "china", "province" : "jiangsu" }, // 對象
// "married" : false // 布爾值
// }
// 第一種情況:不出現(xiàn)某成員的名稱(address)
String jsonText = "{" +
" \"phone\" : [\"12345678\", \"87654321\"]," +
" \"name\" : \"yuanzhifei89\"," +
" \"age\" : 100," +
" \"married\" : false," +
"}";
try {
JSONTokener t = new JSONTokener(jsonText);
JSONObject obj = (JSONObject) t.nextValue();
if (obj.optJSONObject("address") == null || obj.isNull("address")){
} catch (JSONException ex) {
ex.printStackTrace();
}
// 第二種情況:成員值為null(address為null)
String jsonText = "{" +
" \"phone\" : [\"12345678\", \"87654321\"]," +
" \"name\" : \"yuanzhifei89\"," +
" \"age\" : 100," +
" \"address\" : null," +
" \"married\" : false," +
"}";
try {
JSONTokener t = new JSONTokener(jsonText);
JSONObject obj = (JSONObject) t.nextValue();
// 應(yīng)該這樣判斷json是否為null
if (obj.get("address") == JSONObject.NULL || obj.isNull("address")) {
} catch (JSONException ex) {
ex.printStackTrace();
}
json中的對象不存在和java中的對應(yīng)關(guān)系:
json中的null對應(yīng)java中的JSONObject.NULL,所以jsonObj.put("key", JSONObject.NULL) 相當(dāng)于{"key" : null}
json中的不出現(xiàn)某成員對應(yīng)Java中的null绿聘,所以jsonObj.put("key", null)相當(dāng)于刪除該成員嗽上,即:{}