JavaScript對象和JSON

JSON(JavaScript Object Notation),指JavaScript的對象表示法,它自己是個字符串,是一種數據交換格式,並不是對象。一般所提的JSON對象實際是JSON字符串解析成對象的結果,或是瀏覽器window對象下的JSON對象。javascript

並且JSON不止用於JavaScript中,其普遍用於數據交換。html

JSON和JavaScript對象

一個JSON文件,或一段JSON字符串,一般是這樣的:java

[{
    "name": "用戶權限管理",
    "code": "99990002",
    "icon": "modicon-1",
    "items": [{
        "name": "模塊權限",
        "code": "999900020009",
        "url": "",
        "isBlank": false,
        "items": [{
            "name": "嚮導模板",
            "code": "9999000200090003",
            "url": "pages/accLayoutTest.html",
            "isBlank": false,
            "items": []
        }, {
            "name": "模塊管理咱們的",
            "code": "9999000200090001",
            "url": "pages/contentPageTest.html",
            "isBlank": false,
            "items": []
        }]
    }]
}, ... ]

而這樣相似的JavaScript對象則是這樣的:git

var menuData = [{
    name: "用戶權限管理",
    code: "99990002",
    icon: "modicon-1",
    items: [{
        name: "模塊權限",
        code: "999900020009",
        url: "",
        isBlank: false,
        items: [{
            name: "嚮導模板",
            code: "9999000200090003",
            url: "pages/accLayoutTest.html",
            isBlank: false,
            items: []
        }, {
            name: "模塊管理咱們的",
            code: "9999000200090001",
            url: "pages/contentPageTest.html",
            isBlank: false,
            items: []
        }]
    }]
}, ...]

二者很是的類似,所不一樣的是就是JavaScript對象中屬性名,也就是對象的key值是能夠沒有引號的,其值爲字符串時,使用''""包裹都可。 所以咱們不少人將第一段代碼塊裏所寫的JSON稱爲JSON對象,實際上,它並非一個對象,只是一個單純的字符串而已,可是它符合JSON的語法規則,能夠很方便地轉化爲JavaScript對象,或者方便地用於數據交換。github

如下咱們來了解一下JSONajax

JSON語法

  • JSON語法規則正則表達式

    JSON 語法是 JavaScript 對象表示語法的子集,其基本原則以下:json

    • 數據在鍵值對中數組

    • 數據由逗號分隔瀏覽器

    • 花括號保存對象

    • 方括號保存數組

  • JSON的值

    • 數字(整數或浮點數)

    • 字符串(在雙引號中)

    • 邏輯值(truefalse

    • 數組(在方括號中[]

    • 對象(在花括號中{}

    • null

JSON做爲一種數據交換格式,爲了保證其能被正確方便的解析,其格式有嚴格的要求,必須遵循如下規則:

  1. 複合類型的值只能是數組對象,不能是函數、正則表達式對象、日期對象。

  2. 簡單類型的值只有四種:字符串、數值(必須以十進制表示)、布爾值和null(不能使用NaN, Infinity, -Infinityundefined)。

  3. 字符串必須使用雙引號表示,不能使用單引號。

  4. 對象的鍵名必須放在雙引號裏面。

  5. 數組或對象最後一個成員的後面,不能有逗號。

  6. 數值前不能加0。

如下是合法的JSON格式示例:

["one", "two", "three"]

{
    "one": 1,
    "two": 2,
    "three": 3
}

{
    "names": [
        "張三",
        "李四"
    ]
}

[
    { "name": "張三" },
    { "name": "李四" }
]

下面這些就是不合法的:

{
    name: "張三",
    'age': 32
} // 屬性名必須使用雙引號

[32, 64, 128, 0xFFF] // 不能使用十六進制值

{
    "name": "張三",
    "age": undefined
} // 不能使用undefined

{
    "name": "張三",
    "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
    "getName": function() {
        return this.name;
    }
} // 不能使用函數和日期對象

{
    "name": "李四",
    "age": 018
} // 數值前不能有0

以上代碼中爲了指出錯誤所在,使用了JavaScript的註釋法,實際JSON中是不能有註釋的。

不合法的JSON會在解析成JavaScript對象時,出現錯誤。

JSON和JavaScript對象的轉化

window.JSON

JSON做爲一種數據交換格式,被寫入了ECMAScript 5,在IE8及以後的瀏覽器都提供了一個JSON對象,用於對JSON進行解析和序列化。

JSON.parse()

此方法接收一個JSON字符串,返回解析後的JavaScript對象,一般爲ObjectArray

// JSON數據
var humansData = '[{"name":"zs","age":28},{"name":"ls","age":26}]';
// 解析爲JavaScript對象
var humans = JSON.parse(humansData);

// 以後就能夠訪問其元素或屬性了
humans[1].name; // ls
humans[1].age; // 26

若是傳入不合法的JSON,則會在JSON.parse時報錯。

爲何咱們在ajax請求中,即便請求的數據爲JSON,咱們不用解析就能直接使用呢?

// test.text內容
/*
[{
    "name":"zs",
    "age":28
},{
    "name":"ls",
    "age":26
}]
*/

$.ajax({
    url: './test/test.text',
    dataType: 'JSON'
}).done(function(data){
    console.dir(data); // Array[2]
    console.log(data[0].name); // zs
    // 這裏沒有轉化爲js對象就能訪問其屬性?!    
});

這裏實際是由於指定了dataType爲JSON,從而進行了自動轉化,因此能直接在成功回調中使用其屬性。若是去掉dataType的指定,就不能直接訪問其屬性了,由於未轉化時,其自己是一個字符串。第一行輸出爲test.text的內容,第二行輸出undefined

JSON.stringify()

此方法可接收一個JavaScript值將轉化爲JSON字符串,此字符串可被JSON.parse還原。

var humans = [{
    "name": "zs",
    "age": 28,
    "birth": new Date()
}, {
    "name": "ls",
    "age": 26,
    "birth": new Date()
}];

// 轉化爲JSON字符串
JSON.stringify(humans);
// "[{"name":"zs","age":28,"birth":"2016-10-25T07:24:11.701Z"},{"name":"ls","age":26,"birth":"2016-10-25T07:24:11.701Z"}]"

前面咱們講到了JSON中並不是支持全部的JavaScript類型,所以此方法對一些JSON不可接受的值有所處理:原始對象中,若是有一個成員的值是undefined、函數或XML對象,這個成員會被省略。若是數組的成員是undefined、函數或XML對象,則這些值被轉成null。

咱們還發現,JSON中是不支持Date對象的,而上述轉化爲字符串的結果中正確包含了birth的值,其爲一個日期格式的字符串。這是由於在Date對象上有一個名爲toJSON的方法,JSON.stringify在序列化時,實際是調用了這個方法來輸出結果的。

若是一個被序列化的對象擁有 toJSON 方法,那麼該 toJSON 方法就會覆蓋該對象默認的序列化行爲:不是那個對象被序列化,而是調用 toJSON 方法後的返回值會被序列化,例如:

var obj = {
    foo: 'foo',
    toJSON: function() {
        return 'bar';
    }
};

JSON.stringify(obj); // '"bar"' 
JSON.stringify({x: obj}); // '{"x":"bar"}'

瞭解便可,詳見: MDN:JSON.stringify(){.doc-link}

咱們可能常常看到的是JSON.stringify( obj , null , 4),這樣是什麼意思呢?

對於上例,替換最後一句,結果以下所示:

JSON.stringify(humans, null, 4);
// "[
//     {
//         "name": "zs",
//         "age": 28,
//         "birth": "2016-10-25T07:24:11.701Z"
//     },
//     {
//         "name": "ls",
//         "age": 26,
//         "birth": "2016-10-25T07:24:11.701Z"
//     }
// ]"

其實沒什麼變化,不過是加上了空格縮進,使得可讀性更高了。

其他兩個參數的說明以下:

  • 第二個參數可指定序列化時的操做。

    • 若是該參數是一個函數,則在序列化過程當中,被序列化的值的每一個屬性都會通過該函數的轉換和處理;

    • 若是該參數是一個數組,則只有包含在這個數組中的屬性名纔會被序列化到最終的 JSON 字符串中;

    • 若是該參數爲null或者未提供,則對象全部的屬性都會被序列化;

  • 第三個參數用於指定縮進用的空白字符串,用於美化輸出(pretty-print);

    • 若是參數是個數字,它表明有多少的空格;上限爲10。該值若小於1,則意味着沒有空格;

    • 若是該參數爲字符串(字符串的前十個字母),該字符串將被做爲空格;

    • 若是該參數沒有提供(或者爲null)將沒有空格。

替代方法

window.JSON對象下雖然提供了完整的JSON字符串和JavaScript對象的轉換方法。可是在IE8(兼容模式)以及更低版本的IE下沒有提供這個對象,所以咱們須要一些替代方案。

  • jQuery中提供了parseJSON這樣一個方法來替代JSON.parse,它接收一個標準格式的JSON字符串,返回一個解析後的JavaScript對象。

  • 使用http://www.json.org/提供了一個json.js,這樣ie8(兼容模式),ie7和ie6就能夠支持JSON對象以及其stringify()parse()方法; 能夠在https://github.com/douglascrockford/JSON-js上獲取到這個js,通常如今用json2.js。

  • 還可使用 eval('(' + jsonstr + ')') ; 來將json字符串轉換成json對象,注意須要在json字符外包裹一對小括號。但最好不要使用這種方式,由於這種方式不安全,eval會將JSON字符串做爲JavaScript語句來執行,JSON中的風險代碼將被執行。

參考連接

JSON

JSON對象

根本沒有「JSON對象」這回事!

JavaScript標準庫-JSON對象

js對象與JSON字符串互轉

個人博客 - JavaScript 原型鏈

相關文章
相關標籤/搜索