深入解析

妖精的绣舞 提交于 2019-12-03 09:07:41

  前言

    想要比较清楚的研究一个东西,并不是说背下它的定义和几个公式就完事了.所以对于JSON的解释我也没有兴趣再COPY一遍它的英文全称和完整命名,大家都知道它是一种数据交换格式,平时也就是当作一种数据类型那么用了,这一点问题都没有,本文只是在了解它的基本概念和前提上稍微深入一下.

  正文

    1. JSON格式
 

    2001年为了取代繁琐而笨重的XML格式,JSON作为一种轻量级的数据交换格式被提出,作为1999年ECMA-262的一个子集.一经提出JSON就迅速的在Web应用上普及开来,因为相比于XML,JSON书写十分简单方便阅读,同时因为是Javascript的子集所以符合JS的原生语法,可以被解释引擎直接处理.
 

    数据格式存在的目的是以一定的形式存储数据,简单说,JSON格式就是一种表示一系列"值"的方法,这些"值"存在于数组或者对象当中.
 

    JSON虽然可以存储值,但是也要遵守一定的规则,当然结构的核心就是"key/vlaue".
 

    Object - 对象是一个无序的"key/value"集合.


    Array - 数组是值的有序集合.


    Value - 值可以是双引号括起来的string,number,true,false,null,object,array,这些结构还可以嵌套使用.


    String - 被双引号包围的任意Unicode字符集合.


    Number - 数值与C和Java的数值很相似.


    看了上面的结构,下面列举一些书写正确和错误的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;
  }
} // 不能使用函数和日期对象

    注意空数组和空对象都是符合规范的JSON值,null本身也没有问题.看到这里应该对JSON的格式有所了解了,最起码纠正大家一个误区,JSON不一定非要是{}或者[],而是两者均可. 

    2. JSON对象

    我们之前提到了JSON诞生于2001年,是ECMA-262的一个子集,后来JSON因为其流行程度以及实用性被加入到ECMA标准中.在ECMA5新增了JSON对象专门用来处理JSON格式,并且附加了stringify()和parse()两个方法.

    平时开发中有时我们将JSON理解为一个通过大括号和中括号进行结构标记的很长的字符串,这么理解我感觉也没错.

    JSON.stringify(o) - 用于将对象转为JSON字符串.    JSON.parse(string) - 用于将JSON字符串转为对象.

    (1) stringify()

JSON.stringify("abc");
// ""abc""

JSON.stringify({ name: "张三" });
// {"name":"张三"}

    这里转为的时候如果遇到一个值是undefined或者是函数,那么该值会被省略,除非这个值是数组的成员,则返回null. 

JSON.stringify({
    f: function() { },
    a: [ function() {}, undefined ]
});
// "{"a":[null,null]}"

    第一个参数是要转换的对象,第二个参数可以没有,也可以是数组参数表示要转化的属性,或者是一个函数用来更改默认的转换.

JSON.stringify({ a:1, b:2 }, ['a']);
// "{"a":1}"

function f(key, value) {
        if (typeof value === "number") {
            value = 2 * value;
        }
        return value;
    }

JSON.stringify({ a:1, b:2 }, f)
// "{"a":2,"b":4}"

    stringify()方法还可以接受第三个参数用来增强返回字符串的可读性,以及更复杂的使用.但是这里不推荐大家这么用,因为使用JSON的目的就是为了简洁明了,如果把数据格式弄得太复杂就失去了本身含义了,所以通常情况下"对象数组"这种复杂度应该足够了.

    (2) parse()

    想要将一个字符串转换为JSON对象,那么传入的字符串一定要是有效的格式,否则程序会出错,为了防止意外可以将这个过程放到try/catch代码块中.

JSON.parse('{}'); // {}
JSON.parse('true'); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null'); // null

var o = JSON.parse('{"name":"张三"}');

o.name
// 张三

    它也可以接受一个第二参数,通过一个函数改变默认转换的行为.

function f(key, value) {

  if ( key === ""){
      return value;
  }
    
  if ( key === "a" ) {
    return value + 10;
  }
}

var o = JSON.parse('{"a":1,"b":2}', f);

o.a
// 11

o.b
// undefined

    3. 误区

    非常多的人在使用了很久的JSON后都没有弄明白什么是JSON,虽然上面将来字符串和JSON对象的转换.但是我依然要纠正,javascript中没有一种数据类型叫做"JSON对象".可以说JSON对象是在一种特殊环境上下文中产生的叫法,JSON在日常的表现形式更多的是一个拥有复杂数据结构的字符串,只是可以被转换为对象.

// 这是JSON字符串
var foo = '{ "prop": "val" }';
 
// 这是对象字面量
var bar = { "prop": "val" };

    4. 一点点扩展 - JSONP    

    说到这里JSON就没什么东西了,作为一种数据格式在外面日常使用的范畴它的深度也差不多就是这些了.写着JSON到最后想起来了JSONP,所以顺带着也把它带出来.

    看名字就会觉得JSON和JSONP有那么点好基友的味道,根据百度百科对JSONP的解释是:JSON with Padding的略称,一个非官方协议,允许在服务器集成Script tags返回给客户端,通过JS callback的形式实现跨域访问.

    说到跨域我象看过的人应该对JSONP有一点印象,比较经典的说跨域的文章几乎都提到了一种解决方案就是JSONP.这里我不想解释跨域的相关问题,所以我就针对JSONP解读一下:

    Ajax在请求文件时只要是跨域请求一概不准,但是Web页面上调用JS文件则不受跨域的限制,于是我们就想出一种方案,把服务器上的数据设法装进JS格式的文件里,然后让客户端调用.这时我们想到JSON被JS原生支持而且可以存储复杂数据,这下好了,web端通过与调用脚本一样的方式,调用跨域服务器上动态生成的js格式文件,客户端在对这种JSON文件调用成功后就可以随便使用了.为了方便客户端使用数据,逐渐形成一种非正式的传输协议,被称为JSONP,它规定允许用户传递一个callback参数给服务端,然后服务器返回数据时会将这个callback参数作为函数名来包裹JSON数据.

    结尾

    关于JSON和相关的东西就写了这些,参考了网上一些资料和自己的使用心得,水平有限,有不足的地方还请谅解,欢迎留言给我.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!