什么是JSON—通用的数据格式

560 阅读10分钟

什么是JSON?通用的数据格式

JSON是网络应用和其他方面的主要数据交换格式。下面是你需要知道的关于JavaScript对象符号的内容。

JSON,即JavaScript对象符号,是一种用于表示数据的格式。它在21世纪初作为JavaScript的一部分被引入,并逐渐扩展到成为描述和交换基于文本的数据的最常见的媒介。今天,JSON是数据交换的普遍标准。它出现在编程的每个领域,包括前端和服务器端开发、系统、中间件和数据库。

这篇文章向你介绍了JSON。你将获得该技术的概述,了解它与类似标准如XML、YAML和CSV的比较,并看到JSON在各种程序和使用案例中的例子。

一点点历史

JSON最初是作为JavaScript客户端和后端服务器之间通信的一种格式而开发的。作为一种人类可读的格式,它很快就得到了普及,前端程序员可以用一种简洁的、标准化的格式与后端进行通信。开发人员还发现,JSON非常灵活:你可以添加、删除和临时更新字段。(这种灵活性是以安全为代价的,后来通过JSON模式解决了这个问题)。

有趣的是,JSON在AJAX革命中得到了普及。鉴于对XML的重视,很奇怪,但正是JSON让AJAX真正大放异彩。将REST作为API的惯例,将JSON作为交换的媒介,这被证明是平衡简单性、灵活性和一致性的有力组合。

接下来,JSON从前端的JavaScript传播到客户端-服务器通信,并从那里传播到系统配置文件、后端语言,一直到数据库。JSON甚至帮助刺激了革新数据存储的NoSQL运动。事实证明,数据库管理员也喜欢JSON的灵活性和易编程性。

今天,像MongoDB这样的面向文档的数据存储提供了一个API,可用于类似JSON的数据结构。在2022年初的一次采访中,MongoDB首席技术官Mark Porter指出,在他看来,JSON仍然在推动数据的前沿发展。 对于一个以简陋的大括号和冒号开始的数据格式来说,这并不坏。

为什么开发人员使用JSON

无论他们在做什么类型的程序或用例,软件开发人员都需要一种方法来描述和交换数据。这种需求在数据库、业务逻辑、用户界面和所有系统通信中都可以找到。有许多方法来构造数据以进行交换。两大阵营是二进制和基于文本的数据。JSON是一种基于文本的格式,所以它可以被人和机器阅读。

JSON是一种非常成功的数据格式化方式,有几个原因。首先,它是JavaScript原生的,它在JavaScript程序中被用作JSON字元。你也可以在其他编程语言中使用JSON,所以它对异质系统之间的数据交换很有用。最后,它是人类可读的。对于一个语言数据结构来说,JSON是一个非常通用的工具。它的使用也相当简单,特别是与其他格式相比。

JSON如何工作

当你在网页上的一个表格中输入你的用户名和密码时,你是在与一个有两个字段的对象互动:用户名和密码。作为一个例子,考虑图1中的登录页面。

IDG

图1.一个简单的登录页面。

清单1显示了使用JSON描述的这个页面。

清单1.登录页面的JSON


{
   username: “Bilbo Baggins”,
   password: “fkj3442jv9dwwf”
}

大括号或小括号({...})内的一切都属于同一个对象。在这种情况下,一个对象在最普遍的意义上是指一个 "单一事物"。大括号内是属于该事物的属性。每个属性都有两个部分:一个名字和一个值,用冒号分开。这些被称为键和值。在清单1中,"用户名 "是一个键,"Bilbo Baggins "是一个值。

属性、字段、和属性

这些元素中的每一个都被用来指代JSON对象的各个部分。从技术上讲,在面向对象的编程语言中,它们被称为成员。每个属性、字段或属性都是一个对象的成员。

这里的关键启示是,JSON做了处理需求所需的一切--在这种情况下,持有表单中的信息--而没有大量的额外信息。你可以看一眼这个JSON文件,就能理解它。这就是为什么我们说JSON是简洁的。简洁性也使JSON成为通过电线发送的优秀格式。

JSON与XML

JSON是作为XML的替代品而创建的,XML曾经是数据交换的主流格式。清单2中的登录表格是用XML描述的。

清单2.XML中的登录表格


<UserLogin>
  <Username>Samwise Gamgee</Username>
  <Password>ghB5fK5</Password>
</UserLogin>

*呀!*光看这个表单就已经很累了。想象一下,要用代码来创建和解析它。相比之下,在JavaScript中使用JSON是非常简单的。试一试吧。在你的浏览器中点击F12,打开一个JavaScript控制台,然后粘贴清单3中的JSON。

清单3.在JavaScript中使用JSON


let hobbitJson = {
    name: "Pippin",
    hometown: "Shire"
}
console.log(hobbitJson.name);  // outputs “Pippin”
hobbitJson.bestFriend = "Merry";  // modify the object
console.log(JSON.stringify(hobbitJson)); //output entire object

// {"name":"Pippin","hometown":"Shire","bestFriend":"Merry"}

XML是很难读的,而且在编码的敏捷性方面还有待改进。JSON的出现就是为了解决这些问题。这也难怪它或多或少地取代了XML。

JSON与YAML和CSV

有时与JSON相比的两种数据格式是YAML和CSV。这两种格式处于时间上的两端。CSV是一种古老的、前数字格式,最终发现它被用于计算机中。YAML的灵感来自于JSON,是其概念上的后裔。

CSV是一个简单的数值列表,每个条目由逗号或其他分隔符表示,并有一个可选的第一行标题字段。它作为一种交换媒介和编程结构是相当有限的,但它对于将大量数据输出到磁盘仍然很有用。当然,CSV对表格数据的组织也非常适合电子表格等东西。

YAML实际上是JSON的超集,这意味着它将支持JSON所支持的任何东西。但YAML也支持一种更精简的语法,目的是为了比JSON更简明。例如,YAML使用缩进的层次结构,放弃了大括号。尽管YML有时被用作数据交换格式,但它最大的用途是在配置文件中。

YAML比JSON好吗?

请看YAML和JSON的区别是什么?了解更多关于这些标准的比较。

复杂的JSON:嵌套、对象和数组

到目前为止,你只看到了JSON用于浅层(或简单)对象的例子。这只是意味着对象上的每个字段都持有一个基元的值。JSON也能够对任意复杂的数据结构进行建模,如对象图和循环图--即具有循环引用的结构。在本节中,你将看到通过嵌套、对象引用和数组进行复杂建模的例子。

带有嵌套对象的JSON

清单4显示了如何定义嵌套的JSON对象。

清单4.嵌套的JSON


let merry = { name: "Merry",
  bestfriend: {
    name: "Pippin"
  }
}

清单4中的bestfriend 属性指的是另一个对象,它被定义为JSON字面的内联。

带有对象引用的JSON

现在考虑清单5,在这里我们不是在bestfriend 属性中持有一个名字,而是持有对实际对象的引用。

清单5.一个对象引用


let merry = { race: "hobbit", name: “Merry Brandybuck” }
let pippin = {race: "hobbit", name: “Pippin Took”, bestfriend: merry }
console.log(JSON.stringify(pippin.bestfriend.name)); // outputs “Merry Brandybuck”

在清单5中,我们把merry 对象的句柄放在bestfriend 属性中。然后,我们能够通过bestfriend 属性从pippin 对象上获得实际的merry 对象。我们通过name 属性获得了merry 对象的名称。这就是所谓的遍历对象图,这是用点运算符完成的。

带数组的JSON

JSON属性可以有的另一种结构是数组。这些看起来就像JavaScript数组,用方括号表示,如清单6所示。

清单6.一个数组属性


{
  towns: [ “The Shire”, “Rivendale”, “Gondor” ]
}

当然,数组也可以持有对其他对象的引用。有了这两种结构,JSON可以对任何范围的复杂对象关系进行建模。

JSON值类型的总结

到目前为止,你已经看到字符串、对象和数组作为值类型。JSON属性的其他值类型有字符串、数字、对象、数组、真、假和空。

解析和生成JSON

解析和生成JSON意味着分别读取和创建它。你已经看到了JSON.stringify() 的作用。那是JavaScript程序的内置机制,可以把内存中的对象表示法变成一个JSON字符串。要想从另一个方向--即把一个JSON字符串变成一个内存中的对象--你可以使用JSON.parse()

在大多数其他语言中,有必要使用第三方库来进行解析和生成。例如,在Java中,有许多库,但最流行的是JacksonGSON。这些库比JavaScript中的stringifyparse 更为复杂,但它们也提供了先进的功能,如与自定义类型的映射和处理其他数据格式。

在JavaScript中,向服务器发送和接收JSON很常见。例如,使用内置的fetch() API。 这样做时,你可以自动解析响应,如清单7所示。

清单7.用fetch()解析一个JSON响应


fetch('https://the-one-api.dev/v2/character')
  .then((response) => response.json())
  .then((data) => console.log(data));

一旦你把JSON变成一个内存数据结构,无论是JavaScript还是其他语言,你都可以使用API来操作这个结构。例如,在JavaScript中,清单7中解析的JSON将像其他JavaScript对象一样被访问--也许是通过data.keys ,或者访问数据对象的已知属性。

JWTs

认证是另一个使用JSON的领域。开发人员和其他人使用JSON网络令牌,或JWTs,来交流认证要求。JWTs有一个标准的、紧凑的格式,并通过密码学签名来防止篡改。它们也可以被加密以达到保密的目的。

JSON模式和JSON格式化器

JavaScript和JSON具有难以置信的灵活性,但有时你需要比它们提供更多的结构。在像Java这样的语言中,强类型和抽象类型(如接口)有助于构造大规模的程序。在SQL存储中,一个模式提供了一个类似的结构。如果你在你的JSON文档中需要更多的结构,你可以使用JSON模式来明确定义你的JSON对象的特征。一旦定义,你可以使用模式来验证对象实例,确保它们符合模式。

另一个问题是处理机器处理过的JSON,这些JSON已经被压缩,无法辨认。幸运的是,这个问题很容易解决。只要跳到JSON格式化器和验证器(我喜欢这个工具,但也有其他工具),粘贴你的JSON,然后点击处理按钮。你会看到一个你可以使用的人类可读版本。大多数IDE也有一个内置的JavaScript格式化器来格式化你的JSON。

在TypeScript中使用JSON

TypeScript允许定义类型和接口,所以有些时候在TypeScript中使用JSON是有用的。一个类,像一个模式,概述了一个给定类型的实例的可接受属性。在普通的JavaScript中,没有办法限制属性和它们的类型。JavaScript类就像建议;程序员可以现在设置它们,以后再修改JSON。然而,TypeScript 类会强制规定 JSON 可以有哪些属性以及它们可以是哪些类型。

总结

JSON是现代软件领域中最重要的技术之一。它对JavaScript至关重要,但也被用作各种技术之间的通用交互模式。幸运的是,使JSON如此有用的东西使它相对容易理解。它是一种代表文本数据的简洁和可读的格式。