JSON

创建时间:
2014-03-25 22:40
最近更新:
2018-10-02 22:58

Author

Douglas Crockford

Official Website

http://www.json.org/
http://www.json.org/json-zh.html - 官网中文入口
http://www.json.org.cn/

Standard

ECMA 262 Edition5 中提供了原生的 JSON 支持,其中 JSON.parse 用来将字符串转成成 JSON,见 ECMA 262 Edition5 15.12.2。
IE8/Firefox3.5+/Chrome4/Safari4/Opera10 已实现该方法。

ECMA-262(E3) 中没有将 JSON 概念写到标准中,还好在 ECMA-262(E5) 中 JSON 的概念被正式引入了,包括全局的 JSON 对象和 Date 的 toJSON 方法。

JSON 的 ECMA 标准发布
一直以来 JSON 的标准一直是写在 JavaScript 的标准 ECMA-262 标准中的。现在,JSON 终于有了完全属于自己的标准 ECMA-404 标准。
http://www.iteye.com/news/28372

根据 ECMA-262 (ECMAScript) 第 5 版中描述,JSON 是一个包含了函数 parse 和 stringify 的简单对象。
parse 函数用来解析一个 JSON 文本 (一个 JSON 格式的字符串) 到一个 ECMAScript 值 (例如 JSON 对象被解析为 ECMAScript 对象,JSON 数组被解析为 ECMAScript 数组,其它类型以此类推);
stringify 则相反,它将一个 ECMAScript 值解析为一个 JSON 格式的字符串,比如将一个 ECMAScript 对象解析为一个 JSON 对象的字符串。
http://www.w3help.org/zh-cn/causes/SJ9012

Resource

  1. JSON 在线工具
  2. 查询 JSON 数据结构的 8 种方式
  3. Native JSON in IE8
  4. 数据类型和 JSON 格式
  5. jQuery.xml2json - The XML to JSON Plugin (jQuery.xml2json) is a script you can use to convert simple XML into a JSON object.
  6. JSON 生成 C# 类代码小工具 - 类似的工具:"Visual Studio 2013 - 菜单 - 编辑(E) - 选择性粘贴(S) - 将 JSON 粘贴为类(J)"。
  7. JSON 生成 C# 类代码小工具 - 测试页
  8. JSON 数据示例

Resource - 标准是 "双引号 (double quotes)","单引号" 会导致错误

  1. JSON 的标准: 双引号而非单引号
  2. JSON 数据格式中请用双引号而非单引号

Resource - DateTime in JSON

  1. 解决 JSON 日期格式问题的 3 种方法
  2. 关于 DateTime 对象序列化为 JSON 之后的若干问题
  3. JSON 序列化和反序列化日期时间的处理

JSON in IE

IE6 IE7 IE8(Q) 不支持 JSON 对象。

Test in IE

Environment: IE 8.0.7601.17514
Time: 2015-01-22 14:58:10
Tester: Tony

The first set of tests:

//"浏览器模式:IE8 + 文本模式:IE8 标准"
//或
//"浏览器模式:IE8 兼容性视图 + 文本模式:IE8 标准"
JSON //{...}
typeof(JSON) //"object"

The second set of tests:

//"浏览器模式:IE8 + 文本模式:IE8 Quirks"
//或
//"浏览器模式:IE8 兼容性视图 + 文本模式:IE8 Quirks"
JSON //throw error: "'JSON' 未定义"
typeof(JSON) //"undefined"

json2.js

json2.js 提供了 JSON 的序列化和反序列化方法,可以将一个 JSON 对象转换成 JSON 字符串,也可以将一个 JSON 字符串转换成一个 JSON 对象。
https://github.com/douglascrockford/JSON-js

var jsonObject = JSON.parse(jsonString);
var jsonString = JSON.stringify(jsonObject);

json2.js 手册
http://wenku.baidu.com/link?url=ieT8a99jBnjWNRyjYi6F6DZ2bGyDaeCjkOQW-2lx1Ej_onudlIvxKXj_Xhw6hBZ6TWqyUB4Kd4Jitjhx0n34AjAJQxrmcTxjXi6sjffOTg3

json3.js

json3.js 是一个兼容 ECMAScript 5 的 JSON 实现,其目的是兼容一些老的环境,包括:Internet Explorer 6, Opera 7, Safari 2, and Netscape 6.
http://bestiejs.github.com/json3/
http://bestiejs.github.io/json3/

翻译:ECMAScript 5.1 简介
http://www.zhangxinxu.com/wordpress/2012/01/introducing-ecmascript-5-1/

JSON in ECMAScript 5.

/**
@return {string}
*/
String.prototype.toJSON = function() {};

/**
@param {T} thisArg
@param {...*} [arg]
@return {function(this:T)}
@template T
*/
Function.prototype.bind = function(thisArg,arg) {};

/**
@param {*} value
@param {Function} [replacer]
@param {Number|String} [space]
@static
*/
JSON.stringify = function(value,replacer,space) {};
/**
@param {string} jsonString
@param {Function} [reviver]
@static
*/
JSON.parse = function(jsonString,reviver) {};
JSON = function() {};
JSON.constructor = 0;
/**
@static
@return {number}
*/
Date.now = function() {};
/**
@return {string}
*/
Date.prototype.toJSON = function() {};

JavaScript Object to JSON String (仅备份未整理)

jquery.json.js
$.toJSON(Object)

现代浏览器中提供了 JSON.stringify() 方法,用来实现这个功能。
json2.js 中对不支持 JSON.stringify() 的浏览器增加了支持,可以见其源代码。

JSON-js
https://github.com/douglascrockford/JSON-js
http://www.css88.com/archives/3919

JSON in .NET

.NET Framework 自带:

  • System.Web.Script.Serialization.JavaScriptSerializer 类
  • System.Runtime.Serialization.Json.DataContractJsonSerializer 类

第三方:

  • Newtonsoft.Json

Resource

在 .NET 使用 JSON 作为数据交换格式

DateTime in JSON

在中海项目中,Newtonsoft.Json.JsonConvert.SerializeObject(aModel) 生成的 JSON 字符串中,DateTime 类型的数据有时被序列化为类似 { ... "CostApproveDate":"1900-01-01T00:00:00" ... } 的格式。这造成以下两个问题:

问题一:
$.ajax()$.getJSON()$http() 都不能识别这种格式,导致客户端转化为 JavaScript 对象后,这些 DateTime 都是 String 类型、而非 Date 类型。2015-07-01 Tony 使用以下函数解决了此问题。

function DateConverter(object) {
    if(_.isObject(object)) {
        for(var key in object) {
            if(object.hasOwnProperty(key)) {
                var value = object[key];
                if(_.isString(value)) {
                    if(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(value)) {
                        var dateString = DateStringUnify(value);
                        object[key] = new Date(dateString);
                    }
                } else {
                    arguments.callee(object[key]);
                }
            }
        }
    }
}

问题二:
new Date() 支持的参数的格式,各浏览器不一致。2015-07-01 Tony 使用以下函数,兼容了 IE8 与 FF。

function DateStringUnify(dateString) {
    var unify = dateString
        .replace(/-/g, '/') //for IE
        .replace('T', ' ') //for FF
    ;
    return unify;
}

"/Date(1391141532000)/"

"/Date(1391141532000)/" 中的数字是该 Date 对象 "距 1970 年 1 月 1 日之间的毫秒数"。

问题

原因:ASP.NET MVC5 的 JsonResult 类内部用 (new JavaScriptSerializer()).Serialize(something); 生成序列化字符串,该字符串中,DateTime 被序列化为 "/Date(1391141532000)/"
问题:AngularJS 把它当作字符串、而非 Date 对象。
解决:以下是网上常见的解决方案。但 Tony 认为最好的方案是改为使用 Newtonsoft.Json 来执行序列化。

Tony 的方案

//测试发现以下两种 return 的响应头相同:
public ActionResult GetJson(int id)
{
    var entity = CommonBll.GetByKey<CpContractInfo>(id);
    //wrong:
    return Json(entity, JsonRequestBehavior.AllowGet);
    //right:
    string json = Newtonsoft.Json.JsonConvert.SerializeObject(entity);
    return Content(json, "application/json");
}

IIS 不支持 .json ?

在图书馆管理系统原型中,AJAX 请求 .json 文件总是响应 404。修改文件类型后问题已解决。原理有待深究。以下是代码备份:

// .json 导致 404:
app.run(['$rootScope', 'ngsHttp', function(r, h) {
    h.Promise('GET', 'Book.json').success(function(data) {
        r.books = data;
    });
}]);
// 改成 .js 即可:
app.run(['$rootScope', 'ngsHttp', function(r, h) {
    h.Promise('GET', 'Book.js').success(function(data) {
        r.books = data;
    });
}]);

网摘 - 包裹 JSON 的 大括号、中括号、小括号

JSON 通过 重载 大括号 的含义来实现 (原本大括号代表的是代码块的分界,多条语句的集合)。

JSON 不允许区块中的内容按照独立的代码语句来执行。目的是什么? 防止以 <script src=...> 的方式跨域直接调用代码。

但如果获取的数据不是标准的 JSON 格式,那么

 {"hi": alert("HelloWorld!")}       //不执行
({"hi": alert("HelloWorld!")})      //执行
[{"hi": alert("HelloWorld!")}]      //执行

因为中括号和小括号中的内容都代表着表达式,表达式在初始化的时候可能会引起代码执行。

-- JSON Hijacking 小结