2005年, 在Dynamic HTML被重新命名为Ajax后获得了新的能量和关注. Ajax的关键思想之一就是用数据交互作为页面刷新的一个更有效的替代方式. 应用程序使用HTML页面. 那数据应该如何交付呢?
从发展上看, 我们已经看到了数据格式的演变, 从很特殊的方式, 到受数据模型和文档模型所启发的技术. 我们这里要讲述的格式是基于编程语言模型的. 它能够避免特殊方式所带来的脆弱性以及其他模型中遇到的效率低下的问题.
JSON (JavaScript Object Notation)是一种编程语言模型的数据交换格式. 它是JavaScript的一个最小化的、文本化的子集. 具体来说, 他是 ECMA-262(The ECMAScript programming Language Standard, Third Edition, December 1999)的一个子集. 它是轻量级的, 同时也很容易解析.
JSON 不是一种文档格式. 它也不是一种标记语言. 它甚至不能说事一种通用的序列化格式因为它无法表示循环结构, 尽管它可以支持元数据.
很多人都各自发现JavaScript的对象表示, 是面向对象数据传递的一种理想化的数据格式. 我在2001年4月意识到了这一点, 当时我还是State Softwate的CTO. 在2002年, 我拿到了json.org的域名, 然后放了一个描述格式的页面. 然后我也没有做其他方面的努力, 但JSON还是被广泛的使用, 这令它们能够更容易的开发分布式应用和服务. 最开始的页面被翻译成了: 中文、法语、德语、意大利语、日语、韩语和西班牙语. 目前JSON已经正式成为RFC文档, 它的MIME类型是 application/json.
现在, 很多编程语言和系统都有JSON库或内置了JSON支持. 它们是: ActionScript, C, C++, C#, Cold Fusion, D, Delphi, E, Erlang, Haskell, Java, Lisp, LotusScript, Lua, Perl, Objective-C, OCAML, PHP, Python, Rebol, Ruby, Scheme, 和 Squeak.
JSON是基于JavaScript中对象的文本表述. 巧合的是, Python也用同样的符号表述, Newtonscript(John Scully说这将是一万亿美元的产业基础). 还有许多其他的数据格式与JSON非常相似. JSON是一种类C语言的原生的数据表示方式.
JSON中的类型有: 字符串(string)、数值(number)、布尔值(boolean)、对象(object)、数组(array)和空(null). JSON的语法可以用`铁路图`来很好的表示.
JSON 值
字符串(string) 是由双引号包围的任意数量Unicode字符的集合, 使用反斜线转义. 绝大部分编程语言都用了同样的方式.
JSON 字符串
数值(number) 可以表示为整数、实数或者浮点数. JSON不支持八进制和十进制, 因为它是最小化. 它也不支持NaN或者Infinity(无穷大)因为它不想被绑定到一个特殊的内部表示方式. 数值(number) 没有引号包围. 要求用引号将数值包起来, 这太疯狂了.
你会很高兴的知道JSON只有两个布尔值, 那就是 true 和 false. 如果它有全0的布尔值, 它就不是数据格式了.
JSON 对象(object)是一个无序的 键/值 对的集合. 键和值之间用冒号分隔, 键/值对 之间用逗号分隔. 所有这些被大括号包裹. 这直接映射到: 对象、结构、记录、哈希表.
JSON 对象
下面是JSON对象的一个例子:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
JSON数字是用逗号分隔的值得有序集合. 所有这些用方括号包裹. 它直接映射到: 数组、矢量、列表.
下面是JSON数组的一个例子:
JSON 数组
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
[
[0, -1, 0],
[1, 0, 0],
[0, 0, 1]
]
JSON的字符编码是Unicode. UTF-8是唯一有意义的编码. 但UTF-16和UTF-32也同样可以.
JSON没有版本号. 没有修改JSON语法的预期. 如果有1.0, 那就不可避免的有1.1和2.0, 然后在3.0之前, 所有的都没用了. JSON是非常稳定的.
JSON解码器必须支持所有那些格式规整的JSON文本. JSON解码器可以支持非JSON文本. JSON编码器必须只生成格式规整的JSON文本. 这符合Postel法则: "Be liberal in what you accept, and conservative in what you send."
这使得JSON有超集. JavaScript是JSON的一个超集. YAML也是JSON的一个超集. JSON可能会成为有趣的语言/格式课程的核心.
JSON已经成为Ajax中的X. 这是目前Ajax应用程序首选的数据格式. 还有许多在Ajax应用程序中使用JSON的方式. 第一种方法就是在原始的HTML中使用JSON文本.
<html>...
<script>
var data = JSONdata;
</script>...
</html>
这是非常有用的, JSON文本比它所表述的HTML要小得多. 在JavaScript中生成HTML可以使得页面更快的被交付.
最常用的使用JSON的方式是XMLHttpRequest. 一旦得到文本相应, 它就可以很快被转换为JavaScript的数据格式, 然后传递给程序. 有两种方式来做这种转换, 一种是用JavaScript的eval函数, 该函数将调用JavaScript编译器.
responseData = eval('(' + responseText + ')');
这可以正常工作尤为JSON是JavaScript的一个安全子集. 但是这么做有潜在的危险性, 任何服务器发送的内容都将被执行. XMLHttpRequest严格的遵循同源策略. 因此, 只能从源服务器返回内容. 如果服务器作为一个代理而且它没有做合理的过滤, 那么就有可能会在返回文本中包含危险的脚本. 如果存在上述风险, 那么就应该使用parseJSON方法.
responseData = responseText.parseJSON();
parseJSON方法将会在ECMAScript的第四个版本中包含. 在此期间, 一个JavaScript的实现可以在json.org上获取到.
另一种方式是用不可见的<iframe>来做数据通信. 这样就可以在不同的子域之间进行通信. 服务器在script标签中嵌入了JSON文本.
<html><head><script>
document.domain = 'penzance.com';
parent.deliver(JSONtext);
</script></head></html>
deliver函数将会接收传入的数据.
一种更流行的方式是用动态的script标签方式. 它完全绕过了同源策略, 使得我们可以从世界上任何服务器上获取数据. 它比XMLHttpRequest方式更简单. 创建一个script节点, 服务器返回的数据直接嵌入script标签中.
deliver(JSONtext);
deliver函数将会接收到传入的数据. 在它被评估之前, 我们没有办法检查相应, 因此我们无法防范恶意服务器发送危险的脚本来替代正常的JSON文本. 动态脚本标记是不安全的方式. 它不应该被使用.
我正在建议一种新的数据通讯方式, 将允许任何页面与任何服务器之间可以双向安全的交换数据. 它可以在不引入新的安全缺陷的情况下避免同源策略的限制. 请告诉你喜欢的浏览器制造商: "我要JSONRequest!", 你可以在这里获取更多的信息: http://www.JSON.org/JSONRequest.html
现在, 你的JavaScript程序已经获取到了数据. 然后可以做什么呢? 最简单的事当然就是客户端的HTML生成.
var template = '<table border="{border}"><tr><th>Last</th><td>{last}</td></tr>' + '<tr><th>First</th><td>{first}</td></tr></table>';
注意, 我们有三个变量的HTML模板. 然后我们获取一个包含了相同成员变量的JSON对象.
var data = {
"first": "Carl",
"last": "Hollywood",
"border": 2
};
我们可以用supplant方法来向模板中填入数据.
mydiv.innerHTML = template.supplant(data);
JavaScript的字符串没有supplant方法, 但可以这样做因为JavaScript允许我们增加内置类型, 并且赋予它们我们所需要的特性.
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' ?
r : a;
}
);
};
JSONT包中有一个更有趣的转换类.
例如, 我们用一个包含规则集合的对象(这里, 规则可以是模板, 模式或者JavaScript函数)和一个结构复杂的数据对象来调用 jsonT.
var rules = {
self: '<svg><{closed} stroke="{color}" points="{points}" /></svg>',
closed: function (x) {return x ? 'polygon' : 'polyline';},
'points[*][*]': '{$} '
};
var data = {
"color": "blue",
"closed": true,
"points": [[10,10], [20,10], [20,20], [10,20]]
};
jsonT(data, rules);
<svg><polygon stroke="blue" points="10 10 20 10 20 20 10 20 " /></svg>
JavaScript是一门强大的语言, 它使得JSONT转换器还不到一页的代码. 参见: http://goessner.net/articles/jsont/
那些XML里适合用作数据交互的特性在JSON里得到了增强.
同时可供人类和机器阅读.
两种格式都是这样的.
它支持Unicode, 允许几乎人类所有语言传达的信息进行交互.
JSON只支持Unicode
自己录的格式来描述结构和字段名称, 以及具体的值.
同样的, 两者都是这样的. 但这又引出了另外的问题: 既然格式都自描述了, 那它为什么还需要 schema ?
严格语法和解析要求允许必要的解析算法简单、高效、一致.
JSON的语法明显更简单, 因此解析起来效率更高.
能够代表最常用的计算机数据机构: 记录、列表和树.
这个是最显著的区别. 虽然我们可以通过一些转换来用XML来表示这些结构, JSON更直接. JSON基本的值和编程语言是一样的. JSON的结构看起来就是传统编程语言的结构, 不需要额外的结构调整. JSON的对象是记录、结构、对象、字典、哈希或者索引数组. JSON的数组是数组、矢量、队列或者列表.
JSON没有名字空间. 每个对象就是一个名字空间: 它的键是独立于其他对象的. 甚至不包括嵌套的JSON. JSON使用上下文来避免歧义, 就像编程语言一样.
JSON没有验证器. 拥有良好格式和有效的是不同的, 就好比正确和有关的一样. 最终, 每个应用程序需要自己来验证输入的有效性. 这不能分隔. YAML是一个验证器, 既然YAML是JSON的一个超集, 可以使用这个验证器.
JSON是不可扩展的. 也不需要扩展. 它可以表示任意非经常性的数据结构. JSON是灵活的. 新的字段可以在不修改现有代码的基础上添加到结构中. 从这方面来讲, XML也不是可扩展的. 它可以新增标签和属性, 但它无法扩展XML来增加数组、对象、数值和布尔值的语法.
原文: JSON: The Fat-Free Alternative to XML
地址: http://www.json.org/fatfree.html