【JavaScrpt 漫游】【015】JSON 对象简记


文章简介

本文为【JavaScript 漫游】专栏的第 015 篇文章,主要是对 JS 语言中的 JSON 对象的知识点进行了简要记录。

  1. JSON 格式
  2. JSON 对象
  3. JSON.stringify()
  4. JSON.parse()

JSON 格式

JSON 格式(JavaScript Object Notation 的缩写)是一种用于数据交换的文本格式,2001年被提出,目的是取代繁琐笨重的 XML 格式。

相比 XML 格式,JSON 格式有两个显著的优点:书写简单,一目了然;符合 JS 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON 迅速被接受,已经成为各大网站交换数据的标准格式,并被写入标准。

每个 JSON 对象就是一个值,可能是一个数组或对象,也可能是一个原始类型的值。总之,只能是一个值,不能是两个或更多的值。

JSON 对值的类型和格式有严格的规定。

  1. 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象
  2. 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN、Infinity、-Infinity 和 undefined)
  3. 字符串必须使用双引号表示,不能使用单引号
  4. 对象的键名必须放在双引号里面
  5. 数组或对象最后一个成员的后面,不能加逗号

要注意的是,null、空数组和空对象都是合法的 JSON 值。

JSON 对象

JSON 对象是 JS 的原生对象,用来处理 JSON 格式数据。它有两个静态方法:JSON.stringify() 和 JSON.parse()

JSON.stringify() 用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,并且可以被 JSON.parse() 方法还原。

js 复制代码
JSON.stringify('abc') // ""abc""
JSON.stringify(1) // "1"
JSON.stringify(false) // "false"
JSON.stringify([]) // "[]"
JSON.stringify({}) // "{}"
JSON.stringify([1, "false", false])
// '[1,"false",false]'
JSON.stringify({ name: "张三" })
// '{"name":"张三"}'

注意,对于原始类型的字符串,转换结果会带双引号

js 复制代码
JSON.stringify('foo') === "foo" // false
JSON.stringify('foo') === "\"foo\"" // true

这是为了将来还原的时候,内层双引号可以让 JS 引擎知道,这是一个字符串,而不是其他类型的值。

js 复制代码
JSON.stringify(false) // "false"
JSON.stringify('false') // "\"false\""

如果对象的属性是 undefined、函数或 XML 对象,该属性会被 JSON.stringify 过滤。

js 复制代码
var obj = {
  a: undefined,
  b: function () {}
};
JSON.stringify(obj) // "{}"

如果数组的成员是undefined、函数或 XML 对象,则这些值被转成 null

js 复制代码
var arr = [undefined, function() {}];
JSON.stringify(arr); // "[null, null]"

正则对象会被转为空对象

js 复制代码
JSON.stringify(/foo/) // "{}"

JSON.stringify 会忽略对象的不可遍历的属性。

js 复制代码
var obj = {};
Object.defineProperties(obj, {
  'foo': {
    value: 1,
    enumerable: true
  },
  'bar': {
    value: 2,
    enumerable: false
  }
});
JSON.stringify(obj); // "{"foo":1}"

JSON.stringify 方法还可以接受一个数组,作为第二个参数,指定需要转成字符串的属性。

js 复制代码
var obj = {
  'prop1': 'value1',
  'prop2': 'value2',
  'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"

这个类似白名单的数组,只对对象的属性有效,对数组无效。

js 复制代码
JSON.stringify(['a', 'b'], ['0'])
// "["a","b"]"
JSON.stringify({0: 'a', 1: 'b'}, ['0'])
// "{"0":"a"}"

第二个参数还可以是一个函数,用来更改JSON.stringify的返回值。

js 复制代码
function f(key, value) {
  if (typeof value === "number") {
    value = 2 * value;
  }
  return value;
}
JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'

JSON.stringify 还可以接受第三个参数,用于增加返回的 JSON 字符串的可读性。如果是数字,表示每个属性前面添加的空格(最多不超过10个);如果是字符串(不超过10个字符),则该字符会添加到每行前面。

js 复制代码
JSON.stringify({ p1: 1, p2: 2 }, null, 2);
/*
"{
  "p1": 1,
  "p2": 2
}"
*/

JSON.stringify({ p1:1, p2:2 }, null, '|-');
/*
"{
|-"p1": 1,
|-"p2": 2
}"
*/

参数对象的 toJSON 方法

如果参数对象有自定义的 toJSON 方法,那么 JSON.stringify 会使用这个方法的返回值作为参数,而忽略原对象的其他属性。

js 复制代码
var user = {
  firstName: '三',
  lastName: '张',
  get fullName(){
    return this.lastName + this.firstName;
  },
  toJSON: function () {
    return {
      name: this.lastName + this.firstName
    };
  }
};

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

JSON.parse()

JSON.parse 方法用于将 JSON 字符串转换成对应的值。

js 复制代码
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 // 张三

如果传入的字符串不是有效的 JSON 格式,JSON.parse 方法将报错。

js 复制代码
JSON.parse("'String'") // illegal single quotes
// SyntaxError: Unexpected token ILLEGAL

上面代码中,双引号字符串中是一个单引号字符串,因为单引号字符串不符合 JSON 格式,所以报错。

为了处理解析错误,可以将 JSON.parse 方法放在 try...catch 代码块中。

js 复制代码
try {
  JSON.parse("'String'");
} catch(e) {
  console.log('parsing error');
}

JSON.parse 方法可以接受一个处理函数,作为第二个参数,用法与 JSON.stringify 方法类似。

js 复制代码
function f(key, value) {
  if (key === 'a') {
    return value + 10;
  }
  return value;
}
JSON.parse('{"a": 1, "b": 2}', f)
// {a: 11, b: 2}
相关推荐
传人once6 分钟前
企业官网静态页基础结构如何搭
javascript·css
桔筐10 分钟前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
damoluomu15 分钟前
静态站点生成器怎么选:Node.js 生态里常用的五个(番外一)
javascript·css·typescript·node.js·html
小马过河R28 分钟前
EdgeOne深度解析:从原理、适用场景到COS接入的技术逻辑
java·开发语言·前端·spring·cos
ZoeLandia1 小时前
TypeScript 04:类型断言与类型守卫
开发语言·前端·typescript
guzicheng19901 小时前
webpack 安装笔记:全局 vs 本地,以及一个 PATH 环境变量的坑
前端·webpack
西索斯coding1 小时前
Claude Code 工具调用返回空怎么办?claude-opus-5.5 的 input_schema 校验踩坑记录与修复方案
服务器·前端·javascript·ai
疯狂敲代码的老刘1 小时前
MarvellousSuspender浏览器扩展:1.4K星开源标签页冻结神器,Chrome吃内存终结者的干净复活版
前端·chrome
码上上班1 小时前
shell 脚本知识点总结
前端·chrome
程序员Sunday1 小时前
Flex 和 Grid 有什么区别?一维布局、二维布局怎么选?
前端·css·面试