JSON的学习总结,知识归纳

posted @ Oct 21, 2015

最近使用JSON很频繁,索性就好好整理一番,其实思路就是《Javascript高级程序设计》里面的提炼。

概念解释

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。 —————百度

JSON 全称为 JavaScript Object Notation(JavaScript对象表示法),它利用与 JavaScript 对象相似的表示方法来表示数据。虽然 JSON 脱胎于 JavaScript,但是 JSON 并不属于 JavaScript 的一部分,很多的语言都可以解析和序列化 JSON。

数据特点

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • 是轻量级的文本数据交换格式
  • JSON 语法是 JavaScript 对象表示法语法的子集,但独立于任何语言之外
  • 具有自我描述性,更易理解
  • 可通过 JavaScript 进行解析
  • 纯文本,数据可使用 AJAX 进行传输

JSON语法规则

数据结构

JSON 语法是 JavaScript 对象表示法语法的子集。

  • 数据在名称/值对中,数据由逗号分隔,花括号保存对象,方括号保存数组,对象的属性必须要用双引号引起来,单引号会出错,同时JSON里没有变量的概念,也没有length属性。

  • 需要注意的是,也是与 JavaScript对象表示方法的不同之处,JSON 字符串当中对象的属性必须加上双引号。(再强调一遍)

  • JSON简单值一般很少用,就在在大括号里填充数据。简单值包括字符串、数值、布尔值和 null。

  • JSON对象是名/值对的集合,类似于Python中的字典,对象,与 JavaScript对象相似,表示无序的键值对。键值对中的值可以是简单值,也可以是对象或数组。

  • JSON数组是值的有序列表,类似于Javascript中的数组。表示一组有序的值,数组的值可以是简单值,也可以是对象或数组。

表示记号

  • 花括号(’{‘,’}’):表明一个对象,
  • 中括号(’[’,’]’):表明一个数组,
  • 逗号(’,’):表示并列关系,
  • 任何空白符(空格、回车符、制表符等):为了视觉上的好看。

值的类型

  • 字符串:C语言的风格,可包含转义字符,使用Unicode字符,
  • 数值:C语言风格,可采用e/E来科学记数,小数等,
  • true:“真”,false:“假”,
  • null:表示无内容,
  • 对象:上面说的名/值对的集合,
  • 数组:值的有序列表。

注意​

除以上6种外,再无其他,没有像js一样的undefined、NAN

1) 并列的数据之间用逗号(", ")分隔。
2) 映射用冒号(": ")表示。
3) 并列数据的集合(数组)用方括号("[]")表示。
4) 映射的集合(对象)用大括号("{}")表示。

举例

一个例子(JSON对象):

{
    "name": "kaychen",
    "age": 23,
    "address": {
        "province": "HuBei",
        "city": "WuHan"
    },
    "gender": true,
    "contact": [
        "office": "1234-7654321",
        "private": "15671592309"
    ],
    "friends": ["bc", "cc", "dc"],
    "blog": "http://littlewhitechen.github.io/"
}

一个例子(JSON数组):

[
    "Tom": {
        "title": "professor",
        "department": "logistic",
        "salary": 6516.52
    },
    "Jerry": {
        "title": "teacher",
        "department": "logistic",
        "salary": 4358.64
    }
]

从上可以看出,JSON可以无限嵌套。

JSON语法解析

原始的eval()解析

在 JSON 诞生之初 JavaScript 处理 JSON 的方式基本就靠 eval() 函数。 eval() 函数使用的是 JavaScript 编译器,可解析 JSON 文本,然后生成 JavaScript 对象。必须把文本包围在括号中,这样才能避免语法错误:var obj = eval (“(“ + txt + “)”);

<body>
    <p>
        First Name: <span id="fname"></span>
        <br /> Last Name: <span id="lname"></span>
        <br />
    </p>
    <script type="text/javascript">
    var txt = '{"employees":[' + //注意javascript的字符串连接的规则
        '{"firstName":"Bill","lastName":"Gates" },' +
        '{"firstName":"George","lastName":"Bush" },' +
        '{"firstName":"Thomas","lastName":"Carter" }]}';
	var obj = eval("(" + txt + ")");
    document.getElementById("fname").innerHTML = obj.employees[1].firstName
    document.getElementById("lname").innerHTML = obj.employees[1].lastName
    </script>
</body>

原生序列化和解析

在浏览器中,这提供了原生的 JSON 支持,而且 JSON 解析器的速度更快。 eval() 函数可以解析 JSON 然后返回 JavaScript 数组。但是由于 eval() 存在安全的风险,因此在 EMCAScript 5 开始有了一个新的全局对象 JSON对象用来处理 JSON。

较新的浏览器和最新的 ECMAScript (JavaScript) 标准中均包含了原生的对 JSON 的支持。

stringify()

JavaScript使用JSON对象的stringify()方法来序列化Javascript,将其转换成JSON。

var person = {
    "name": "kaychen",
    "age": 23,
    "address": {
        "province": "HuBei",
        "city": "WuHan"
    },
    "gender": true,
    "contact": [
        "office": "1234-7654321",
        "private": "15671592309"
    ],
    "friends": ["bc", "cc", "dc"],
    "blog": "http://littlewhitechen.github.io/"
}

var jsonText = JSON.stringify(person);
// 结果自己可以尝试一下

JSON.stringify() 方法在默认情况下输出的 JSON字符串不包含空格字符和缩进。

如果 JavaScript对象当中包含不被 JSON 支持的类型(如:undefined,函数,正则表达式)会自动被 stringigy() 方法忽略。只会输出可以识别的数据。

var person = {
    name: "kaychen",
    blog: undefined,
    todo: function() {
        return "sleep";
    }
};

var jsonText = JSON.stringify(person);

console.log(jsonText);
// {"name":"kaychen"}

JSON.stringify() 方法包含三个参数,第一个参数就是要序列化的 JavaScript对象。第二个参数完成过滤输出结果功能。第三个参数控制输出字符串的缩进。

1、过滤输出结果

第二个参数完成过滤输出结果功能。

当传入的第二个参数为数组时,输出的 JSON字符串只会保留包含在该数组里面的属性值。

var person = {
    name: "kaychen",
    age: 23,
    address: {
        province: "Hubei",
        city: "WuHan"
    },
    friends: ["bc", "cc", "dc"],
    blog: "http://littlewhitechen.github.io/"
};

var jsonText = JSON.stringify(person, ["name","blog"]);

console.log(jsonText);
// {"name":"kaychen","blog":"http://littlewhitechen.github.io/"}

当传入的第二个参数为函数,该函数包含两个参数,分别是 JavaScript对象的属性名和属性值。输出的 JSON字符串会受到该函数的返回值影响。

// 省略 person对象
var jsonText = JSON.stringify(person, function(key, value) {
    if (key === "name") {
        return "ac";
    } else if (key === "age") {
        value++;
        return value;
    } else {
        return value;
    }
});

console.log(jsonText);

// {"name":"ac","age":24,"address":{"province":"HuBei","city":"WuHan"},"friends":["bc","cc","dc"],"blog":"http://littlewhitechen.github.io/"}

2、控制缩进

第三个参数控制输出字符串的缩进。

当第三个参数传入一个数值的时候,表示输出字符串缩进的空格数。

// 省略 person对象
var jsonText = JSON.stringify(person, null, 2);

console.log(jsonText);
// 输出
{
  "name": "kaychen",
  "age": 23,
  "address": {
    "province": "HuBei",
    "city": "WuHan"
  },
  "friends": [
    "bc",
    "cc",
    "dc"
  ],
  "blog": "http://littlewhitechen.github.io/"
}

当第三个参数传入一个字符串时,输出结果会以该字符串作为缩进符号。

// 省略 person对象

// 使用 * 号缩进
var jsonText = JSON.stringify(person, null, "*");

使用制表符(Tab)缩进

// 省略 person对象

// 使用制表符(Tab)缩进
var jsonText = JSON.stringify(person, null, "\t");

3、自定义序列化

如果上述的方法都不能满足要求,还可以在要序列化的 JavaScript对象当中加入 toJSON() 函数,可以返回任何想返回的值。

var person = {
	    "name": "kaychen",
	    "age" 23,
	    "address": {
	        province: "Hubei",
	        city: "WuHan"
	    },
	    "friends": ["bc", "cc", "dc"],
	    "blog": "http://littlewhitechen.github.io/",
	    toJSON: function() {
	        this.name = "ac";
	        return "yoyo " + this.name;
	    }
	};

var jsonText = JSON.stringify(person);

console.log(jsonText);
//  "yoyo ac"

parse()

解析JSON格式数据,JavaScript 使用 JSON对象的 parse() 方法来解析 JSON。经常用来解析从后台服务器获取的JSON格式的数据,然后在前端来调用。

var jsonText = '{"name":"kaychen","age":23,"address":{"province":"Hubei","city":"WuHan"},"friends":["bc","cc","dc"],"blog":"http://littlewhitechen.github.io/"}';

var person = JSON.parse(jsonText);

console.log(person);

{
  "name": "kaychen",
  "age": 23,
  "address": {
    "province": "HuBei",
    "city": "WuHan"
  },
  "friends": [
    "bc",
    "cc",
    "dc"
  ],
  "blog": "http://littlewhitechen.github.io/"
}

JSON.parse(jsonText,function(kay,value){}) 同样可以传入一个函数作为参数,对键值对进行操作。这个函数叫做还原函数,同时这个函数还是接受两个参数,一个键,一个值。而且需要返回一个值。

php中对json的支持

json_encode json_decode json_last_error json_decode的例子:

<?php
   $arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
   echo json_encode($arr);
?>

结果为:

{"a":1,"b":2,"c":3,"d":4,"e":5}

json_decode的原型为

mixed json_decode ($json [,$assoc = false [, $depth = 512 [, $options = 0 ]]])

如果assoc为true,解析json字符串会得到关联数组,相当于python中的字典。 否则会得到对象。

<?php
   $json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

   var_dump(json_decode($json));
   var_dump(json_decode($json, true));
?> 会得到:

object(stdClass)#1 (5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

array(5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

补充:

从结构上看,所有的数据(data)最终都可以分解成三种类型:

  • 第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如”北京”这个单独的词。

  • 第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如”北京,上海”。

  • 第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如”首都:北京”。

在编程语言中,只要有了数组(array)和对象(object)就能够储存一切数据了。

数组和对象的另一个区别是,数组的数据没有”名称”(name),对象的数据有”名称”(name)。

JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number和String。还有1种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。

对一个值使用typeof操作符可能返回下列某个字符串:

  • “undefined”——如果这个值未定义;

  • “boolean”——如果这个值是布尔值;

  • “string”——如果这个值是字符串;

  • “number”——如果这个值是数值;

  • “object”——如果这个值是对象或null;

  • “function”——如果这个值是函数;

Undefined类型:

`Undefined`类型只有一个值,在使用var声明变量但未对其加以初始化时,

这个变量的值就是undefined

Null类型

  Null类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null时会返回”object”的原因,例如:

var car = null;
alert(typeof car); // "object"

Number类型

  这种类型用来表示整数和浮点数值,还有一种特殊的数值,即NaN(非数值 Not a Number)。这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。

String类型

  String类型用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以由单引号(‘)或双引号(“)表示。

数值、布尔值、对象和字符串值都有toString()方法。但null和undefined值没有这个方法。

  多数情况下,调用toString()方法不必传递参数。但是,在调用数值的toString()方法时,可以传递一个参数:输出数值的基数。

var num = 10;
alert(num.toString());      //"10"
alert(num.toString(2));     //"1010"
alert(num.toString(8));     //"12"
alert(num.toString(10));    //"10"
alert(num.toString(16));    //"a"

在不知道要转换的值是不是null或undefined的情况下,还可以使用转型函数String(),这个函数能够将任何类型的值转换为字符串。String()函数遵循下列转换规则:

  ● 如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果

  ● 如果值是null,则返回”null”

  ● 如果值是undefined,则返回”undefined”

Object类型

  对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。而创建Object类型的实例并为其添加属性和(或)方法,就可以创建自定义对象。

var o = new Object();

typeof 操作符

var s = "Nicholas";
var b =true;
var c = 21;
var u;
var n = null;
var o = {};
var obj = new Object;//最好写出new object()形式

alert(typeof s);//string
alert(typeof b);//boolean
alert(typeof c);//number
alert(typeof u);//undefined
alert(typeof n);//object
alert(typeof o);//object
alert(typeof obj);//object

typeof只能检测基本数据类型(除了null),引用数据类型还是的依靠instanceof来检测或者数组的专用Array.isArray()方法