JSON

JSON
JavaScript Object Notation JS对象表示法
JSON和JS对象的格式一样,只不过JSON字符串中的属性名必须加双引号
JSON分类
1.对象{}
2.数组[]

        JSON中允许的值
            1.字符串
            2.数值
            3.布尔值
            4.null
            5.对象(不包括函数对象)
            6.数组

1.JSON.parse()
可以将JSON字符串转换为js对象
它需要一个JSON字符串作为参数,会将该字符串转换成js对象

// 创建一个对象
        var obj = '{"namae":"孙悟空","age":18,"gender":"男"}'
          console.log(JSON.parse(obj));

在这里插入图片描述

2.JS对象转JSON
JSON.stringify()
可以将一个JS对象转为JSON字符串
需要一个js对象作为参数,会返回一个JSON字符串

 var obj3 = {name:"猪八戒",age:28,gender:"男"}
 var str = JSON.stringify(obj3)
       console.log(str);

在这里插入图片描述

3.JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用会报错
如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的json2.js文件(如下)来处理

function test(key,value){
    console.log("this=" + this);
    console.log(key+","+value);
    return value;
}

JSON = function(){};
//-----------------------------------------------------------------------------------------

if (typeof JSON !== 'object') {
JSON = {};
}

(function () {
'use strict';
//这里可以参考http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html
//老版本的浏览器会把它当作一行普通字符串,加以忽略。

function f(n) {
    // 格式化整数(至少要达到两位数)
    return n < 10 ? '0' + n : n;
}

//如果Date的toJSON方法不存在就创建它
if (typeof Date.prototype.toJSON !== 'function') {

    Date.prototype.toJSON = function () {
        //isFinite是原生方法
        return isFinite(this.valueOf())
            ? this.getUTCFullYear()     + '-' +
                f(this.getUTCMonth() + 1) + '-' +
                f(this.getUTCDate())      + 'T' +
                f(this.getUTCHours())     + ':' +
                f(this.getUTCMinutes())   + ':' +
                f(this.getUTCSeconds())   + 'Z'
            : null;
    };

    String.prototype.toJSON      =
        Number.prototype.toJSON  =
        Boolean.prototype.toJSON = function () {
            return this.valueOf();
        };
}


var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    //------------------------------------------------
    //控制字符:[\x00-\x1F\x7F] 其他的还未知 
    escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    //------------------------------------------------
    gap,
    indent,
    meta = {    // 字符替换表格
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\'
    },
    rep;


function quote(string) {

    //如果字符串没有控制字符、引用字符、反斜杠字符,我们可以直接在字符左右两边添加引号;
    //否则,必须先进行替换
    escapable.lastIndex = 0;
    return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
        var c = meta[a];
        return typeof c === 'string'
            ? c
            : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
    }) + '"' : '"' + string + '"';
}


function str(key, holder) {

// 取得holder[key]对应的string

    var i,          // 循环计数器
        k,          // 成员变量key.
        v,          // 成员变量值.
        length,
        mind = gap,
        partial,
        value = holder[key];

//如果value有toJSON方法,就调用它获取替换后的值
    if (value && typeof value === 'object' &&
            typeof value.toJSON === 'function') {
        value = value.toJSON(key);
    }

//如果rep是一个function,就调用它获取替换后的值
    if (typeof rep === 'function') {
        value = rep.call(holder, key, value);
    }

//根据value的类型进行判断
    switch (typeof value) {
    case 'string':
        return quote(value);

    case 'number':

//数字类型必须是有限的,非有限的数字设置成null
        return isFinite(value) ? String(value) : 'null';

    case 'boolean':
    case 'null':

//如果是boolean类型或者null,将它转化成字符串
//需要注意的是typeof null并不等于'null',这里这么写是为了将来修复以后使用。
        return String(value);

//如果是object类型,必须进一步区分出object、array、null类型
    case 'object':

//由于script规范的错误,typeof null == 'object',所以这里区分出了这种情况

        if (!value) {
            return 'null';
        }

//初始化partial数组来存放局部结果
        gap += indent;
        partial = [];

//如果value是数组
        if (Object.prototype.toString.apply(value) === '[object Array]') {

//遍历value中的每一个元素进行stringify,存放到partial数组中,如果不存在,存入"null"字符串到partial数组中。

            length = value.length;
            for (i = 0; i < length; i += 1) {
                partial[i] = str(i, value) || 'null';
            }

//将partial数组中的元素以逗号区分、放到括号内并返回
            v = partial.length === 0
                ? '[]'
                : gap
                ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                : '[' + partial.join(',') + ']';
            gap = mind;
            return v;
        }

//如果replacer参数是数组,use it to select the members to be stringified.
        if (rep && typeof rep === 'object') {
            length = rep.length;
            for (i = 0; i < length; i += 1) {
                if (typeof rep[i] === 'string') {
                    k = rep[i];
                    v = str(k, value);
                    if (v) {
                        partial.push(quote(k) + (gap ? ': ' : ':') + v);
                    }
                }
            }
        } else {

//否则,遍历value中的所有属性
            for (k in value) {
                if (Object.prototype.hasOwnProperty.call(value, k)) {
                    v = str(k, value);
                    if (v) {
                        partial.push(quote(k) + (gap ? ': ' : ':') + v);
                    }
                }
            }
        }

//将partial数组中的元素以逗号区分、放到括号内并返回

        v = partial.length === 0
            ? '{}'
            : gap
            ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
            : '{' + partial.join(',') + '}';
        gap = mind;
        return v;
    }
}

//如果JSON对象没有stringfy方法,就定义它
if (typeof JSON.stringify !== 'function') {
    JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

        var i;
        gap = '';
        indent = '';

//如果space是数字类型,就创建相应大小的空格作为缩进

        if (typeof space === 'number') {
            for (i = 0; i < space; i += 1) {
                indent += ' ';
            }

//如果space是string类型,就将space赋值给indent作为缩进
        } else if (typeof space === 'string') {
            indent = space;
        }

//如果replacer存在,必须是function获取array;否则将抛出异常

        rep = replacer;
        if (replacer && typeof replacer !== 'function' &&
                (typeof replacer !== 'object' ||
                typeof replacer.length !== 'number')) {
            throw new Error('JSON.stringify');
        }

//将value放到key为''的父包装对象中
        return str('', {'': value});
    };
}


//如果JSON对象没有parse方法,就定义它
if (typeof JSON.parse !== 'function') {
    JSON.parse = function (text, reviver) {

//这个方法有两个参数:text和reviver(可选)
//如果json格式正确,返回对应的js对象
        var j;

        function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
//walk方法用来递归调用

            var k, v, value = holder[key];
            if (value && typeof value === 'object') {
                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = walk(value, k);
                        if (v !== undefined) {
                            value[k] = v;
                        } else {
                            delete value[k];
                        }
                    }
                }
            }
            return reviver.call(holder, key, value);
        }


//paring过程分为4个步骤。
//第一个步骤是将unicode字符替换为转义字符。
//js在处理多种字符时是有问题的,不是悄悄的删掉他们,就是把他们当作行结束符。
        text = String(text);
        cx.lastIndex = 0;
        if (cx.test(text)) {
            text = text.replace(cx, function (a) {
                return '\\u' +
                    ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            });
        }
        
//第二个步骤如下:
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

        if (/^[\],:{}\s]*$/
                .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                    .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                    .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

//第三步骤:调用eval命令
//'{'在js中有语法歧义倾向:可以是程序块或者对象字面值。所以这里使用括号来避免歧义            	
            j = eval('(' + text + ')');

//第四步骤(可选):如果reviver是一个function,则递归调用walk方法(参数是name/value对)
            return typeof reviver === 'function'
                ? walk({'': j}, '')
                : j;
        }

// 如果text不可转化,抛出异常
        throw new SyntaxError('JSON.parse');
    };
}
}());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值