JSON和对象字面量表示法有什么区别?

250

有人能告诉我使用对象字面量定义的JavaScript对象和JSON对象之间的主要区别是什么吗?

根据一本JavaScript书籍,以下是使用对象表示法定义的对象:

var anObject = {
    property1 : true,
    showMessage : function (msg) { alert(msg) }
};

为什么这种情况下它不是一个 JSON 对象?只是因为它没有使用引号定义吗?


23
为什么在这种情况下它不是一个JSON对象?因为你的键必须是字符串,而函数不是有效的JSON值。 - Matt
3
可能与JSON和JavaScript对象之间的差异是什么?重复了。 - Lightness Races in Orbit
10个回答

287
首先让我们澄清一下 JSON 到底是什么。JSON 是一种文本格式、与编程语言无关的数据交换格式,类似于 XML、CSV 或 YAML。
数据可以以多种方式存储,但如果要将其存储在文本文件中并可被计算机读取,则需要遵循一定的结构。JSON 是定义这种结构的众多格式之一。
这些格式通常与编程语言无关,这意味着它们可以被 Java、Python、JavaScript、PHP 等语言处理。
相比之下,JavaScript 是一种编程语言。当然,JavaScript 也提供了一种定义/描述数据的方法,但其语法非常特定于 JavaScript。
作为对比,Python 有元组(tuples)的概念,其语法为 (x, y)。JavaScript 没有类似的东西。
让我们来看一下JSON和JavaScript对象字面量之间的语法差异。
JSON有以下语法限制:
- 对象键必须是字符串(即用双引号"括起来的字符序列)。 - 值可以是以下任意一种类型: - 字符串 - 数字 - (JSON)对象 - 数组 - true - false - null - 重复的键({"foo":"bar","foo":"baz"})会产生未定义的、特定于实现的结果;JSON规范明确不定义它们的语义。
在JavaScript中,对象字面量可以具有:
- 字符串字面量、数字字面量或标识符名称作为键(自ES6以来,键现在也可以是计算出来的,这引入了另一种语法)。 - 值可以是任何有效的JavaScript表达式,包括函数定义和undefined。 - 重复的键会产生定义好的、指定的结果(在松散模式下,后一个定义将取代前一个;在严格模式下,这是一个错误)。

看到你的例子,仅从语法上来看,它不是JSON,有两个原因:

  1. 你的键不是字符串(字面量),它们是标识符名称。
  2. 你不能将函数分配为“JSON对象”的值(因为JSON没有定义任何函数语法)。

但更重要的是,重复一下我一开始的解释:你处于JavaScript上下文中。你定义了一个JavaScript对象。如果有的话,“JSON对象”只能包含在字符串中:

 var obj = {foo: 42}; // creates a JavaScript object (this is *not* JSON)
 var json = '{"foo": 452}'; // creates a string containing JSON

如果你正在编写JavaScript源代码并且没有处理字符串,那么你就不是在处理JSON。也许你以JSON的形式接收了数据(例如通过ajax或从文件中读取),但一旦你或你使用的库对其进行了解析,它就不再是JSON了。

仅仅因为对象字面量和JSON看起来相似,并不意味着你可以互换地命名它们。 参见"没有所谓的“JSON对象”"


10
请注意,JSON是对象字面量表示法的一个子集 - Sean Kinsey
15
除了它不是 JavaScript 的子集以外,其他都正确:http://timelessrepo.com/json-isnt-a-javascript-subset - mpen
1
值得注意的是,通常情况下,在允许注释的上下文中,您会期望一个JavaScript对象字面量,而JSON规范不允许注释(请参见此帖子)。 - Brian Henry
对象字面量中的键总是字符串,无论您是否使用""。 - overexchange
2
@overexchange:"对象字面量中的键始终为字符串"。你混淆了两件事,但我不能怪你,因为我也没有在这里划清界限。你必须区分对象字面量和对象字面量是你在源代码中编写的字符序列。是通过解释源代码创建的内容。对象字面量(语法)允许你使用标识符名称字符串字面量数字字面量。你正确地指出,在运行时,所有这些都会转换为字符串(但现在我们也有符号)。 - Felix Kling
显示剩余5条评论

48

JSON有一个更加受限的语法,包括:

  • 键值必须用引号括起来
  • 字符串必须用 " 而不是 ' 括起来
  • 你只能使用一些受限制的值(例如,不允许使用函数)

1
喜欢这个“不允许使用函数”。 - Karan Kaw
出于某些可疑的原因,不允许评论。(我听到过几次质疑。)这是我想说的主要区别。 - user7610

18

实际上并不存在所谓的“JSON对象”。

JSON规范是将数据编码为字符串的一种语法。人们通常称为“JSON对象”的内容(在JavaScript中)实际上只是一个普通的JavaScript对象,它已经被反序列化为有效的JSON字符串,并且可以轻松地重新序列化为有效的JSON字符串。这通常意味着它仅包含数据而不包含函数。这也意味着没有日期,因为JSON没有日期类型(可能是JSON最痛苦的事情;)

此外,(顺便抱怨一下...)当人们谈论“JSON对象”时,他们几乎总是指具有“花括号”作为顶级的数据。这与JavaScript对象相对应得很好。然而,JSON规范并不要求JSON字符串的顶层必须是单个“花括号”对象。在顶级可以是列表,甚至可以只是单个值的情况下,也可以是有效的JSON。因此,虽然每个“JSON对象”都对应有效的JSON,但并非所有有效的JSON字符串都对应于我们所说的“JSON对象”!(因为该字符串可能代表列表或原子值)


5
你的回答中有一个错误:“不合法”的JSON格式不能在顶层使用原子值。JSON格式允许顶层为对象或数组,但不能是其他类型。标准RFC4627将JSON的语法定义为 JSON-text = object / array - Rory O'Kane

10

根据JavaScript中的JSON

JSON是JavaScript对象字面量符号的子集

换句话说,有效的JSON也是有效的JavaScript对象字面量符号,但不一定反过来成立。

除了像@Filix King建议的那样阅读文档之外,我还建议尝试使用JSONLint在线JSON验证器。这就是我学到的JSON对象的键必须是字符串的方法。


2
请注意:这不是完全的子集,有一些JSON字符串在作为JS对象字面量时是无效的。 - Bergi

5

JSON:无XML的减脂替代品

JSON已被广泛采用,使得生产分布式应用程序和服务变得更加容易。JSON的官方互联网媒体类型是application/json,详见RFC 4627。JSON文件名使用扩展名.json


► JavaScript对象表示法(JSON)是一种轻量级的、基于文本的、语言无关的数据交换格式。JSON已被用于在任何编程语言写的应用程序之间交换数据。

JSON对象是一个包含两个函数parse和stringify的单一对象,这些函数用于解析和构造JSON文本。

  • JSON.stringify生成符合以下JSON语法的字符串。
  • JSON.parse接受符合JSON语法的字符串。

parseJSON方法将被纳入ECMAScript第四版。与此同时,可以在json.org中找到Javascript实现。

var objLiteral = {foo: 42}; // JavaScript Object
console.log('Object Literal : ', objLiteral ); // Object {foo: 42}foo: 42__proto__: Object

// This is a JSON String, like what you'd get back from an AJAX request.
var jsonString = '{"foo": 452}';
console.log('JOSN String : ', jsonString ); // {"foo": 452}

// This is how you deserialize that JSON String into an Object.
var serverResposnceObject = JSON.parse( jsonString );
console.log('Converting Ajax response to JavaScript Object : ', serverResposnceObject); // Object {foo: 42}foo: 42 __proto__: Object

// And this is how you serialize an Object into a JSON String.
var serverRequestJSON = JSON.stringify( objLiteral );
console.log('Reqesting server with JSON Data : ', serverRequestJSON); // '{"foo": 452}'

JSON是JavaScript的子集。 Javascript源于ECMAScript编程语言标准。


► ECMAScript

ECMAScript已成为全球使用最广泛的通用编程语言之一。它最为人们所熟知的是,作为嵌入在Web浏览器中的编程语言,但它也被广泛地应用于服务器和嵌入式应用程序。 ECMAScript基于多种技术而产生,其中最著名的是 JavaScript(Netscape Communications)和 JScript(Microsoft Corporation)。)尽管在1994年之前,ECMA被称为“欧洲计算机制造商协会”,但在该组织变成全球性组织后,“Ecma”这个“商标”因历史原因得以保留。

ECMAScript是语言,而JavaScript、JScript甚至ActionScript被称为"方言"

方言是从同一语言衍生出来的。它们彼此相似,因为它们都衍生自同一语言,但它们经历了一些变化。 一个方言是语言本身的变体。它源于单一语言。

  • SQL语言 - Hibernate MySQL Dialect、Oracle Dialect等,它们具有某些变化或添加的功能。

关于您的用户的浏览器和计算机信息。

navigator.appName // "Netscape"

ECMAScript是JavaScript的基础脚本语言。JavaScript 语言资源

ECMA-262链接
初版,1997年6月PDF
第2版,1998年8月PDF
第3版,1999年12月PDF
第5版,2009年12月PDF
第5.1版,2011年6月HTML
第6版,2015年6月HTML
第7版,2016年6月HTML
第8版,2017年6月HTML
第9版,2018年HTML

注意:ECMAScript第四版未被发布,因为工作尚未完成。


JSON定义了一组小型的格式规则,用于结构化数据的可移植表示。

  1. ► Key values must be quoted, only Strings are allowed for keys. If you use other than String it will convert to String. But not recommended to use keys other than String's. Check an example like this - { 'key':'val' } over RFC 4627 - jsonformatter

     var storage = {
       0 : null,
       1 : "Hello"
     };
     console.log( storage[1] ); // Hello
     console.log( JSON.stringify( storage ) ); // {"0":null,"1":"Hello","2":"world!"}
    
     var objLiteral = {'key1':'val1'};
         var arr = [10, 20], arr2 = [ 'Yash', 'Sam' ];
         var obj = { k: 'v' }, obj2 = { k2: 'v2' };
         var fun = function keyFun() {} ;
    
     objLiteral[ arr ] = 'ArrayVal';     objLiteral[ arr2 ] = 'OverridenArrayVal';
     objLiteral[ obj ] = 'ObjectVal';    objLiteral[ obj2 ] = 'OverridenObjectVal';
     objLiteral[ fun ] = 'FunctionVal';
    
     console.log( objLiteral );
     // Object {key1: "val1", 10,20: "ArrayVal", Yash,Sam: "OverridenArrayVal", [object Object]: "OverridenObjectVal", function keyFun() {}: "FunctionVal"}
     console.log( JSON.stringify( objLiteral ) );
     // {"key1":"val1","10,20":"ArrayVal","Yash,Sam":"OverridenArrayVal","[object Object]":"OverridenObjectVal","function keyFun() {}":"FunctionVal"}
     console.log( JSON.parse( JSON.stringify( objLiteral ) ) );
     // Object {key1: "val1", 10,20: "ArrayVal", Yash,Sam: "OverridenArrayVal", [object Object]: "OverridenObjectVal", function keyFun() {}: "FunctionVal"}
    
     console.log('Accessing Array  Val : ', objLiteral[ [10,20] ] );
     console.log('Accessing Object Val : ', objLiteral[ '[object Object]' ] );
     console.log('Accessing Function Val : ', objLiteral[ 'function keyFun() {}' ] );
    
  2. ► JSON Strings must be quoted with " and not '. A string is very much like a C or Java string. Strings should be wrapped in double quotes.

  • 字面量是固定的值,不是变量,在脚本中直接提供。
  • 字符串是用引号括起来的零个或多个字符序列,带有反斜杠转义,与大多数编程语言中使用的符号相同。
  • - 字符串中允许使用特殊符号,但不建议使用。
  • " - 特殊字符可以被转义,但不建议转义单引号 (')。在严格模式下,它将抛出错误 - SyntaxError: Unexpected token ' in JSON

使用此代码 { "Hai\" \n Team ":5, "Bye \'": 7 } 检查在线JSON编辑器。Modes notStrict, Strinct.

    var jsonString = "{'foo': 452}"; // {'foo': 452}
    var jsonStr = '{"foo": 452}'; // {"foo": 452}

    JSON.parse( jsonString ); // Unexpected token ' in JSON at position 1(…)
    JSON.parse( jsonStr ); // Object {foo: 452}

    objLiteral['key'] = 'val'; // Object {foo: 42, key: "val"}
    objLiteral.key2 = 'val';

    // objLiteral.key\n3 - SyntaxError: Invalid or unexpected token
    objLiteral['key\n3'] = 'val'; // Object {"foo": "42", key: "val", key2: "val", "key↵3": "val"}

    JSON.stringify( objLiteral ); // {"foo":"42","key":"val","key2":"val","key\n3":"val"}

对象属性访问器可通过点符号或方括号访问对象的属性。

  1. ► You have a more limited range of values (e.g. no functions allowed). A value can be a string in double quotes, number, boolean, null, object, or array. These structures can be nested.

     var objLiteral = {};
     objLiteral.funKey = function sayHello() {
         console.log('Object Key with function as value - Its outcome message.');
     };
    
     objLiteral['Key'] = 'Val';
    
     console.log('Object Literal Fun : ', objLiteral );
     // Object Literal Fun :  Object {Key: "Val"}Key: "Val"funKey: sayHello()__proto__: Object
     console.log( JSON.stringify( objLiteral ) ); // {"Key":"Val"}
    

进入图像描述


JavaScript 是ECMAScript标准的最受欢迎的实现。 Javascript的核心功能基于ECMAScript标准,但Javascript还有其他ECMA规范/标准中没有的附加功能。 每个浏览器都有一个JavaScript解释器。

Javascript是一种动态类型语言。这意味着在声明变量时无需指定其数据类型,并且数据类型会在脚本执行期间根据需要进行自动转换。

Literals

'37' - 7    // 30
'37' + 7    // "377"
+'37' + 7   // 44
+'37'       // 37
'37'        // "37"

parseInt('37');     // 37
parseInt('3.7');    // 3

parseFloat(3.7);    // 3.7

// An alternative method of retrieving a number from a string is with the + (unary plus) operator:
+'3.7'              // 3.7

对象字面量 RFC 7159

对象结构用一对花括号括起来,包含零个或多个名称/值对(或成员)。名称是一个字符串。每个名称后都跟着一个冒号,将名称与值分开。单个逗号隔开值和下一个名称。应该保证对象中的名称唯一。

ECMAScript支持基于原型的继承。每个构造函数都有一个关联的原型,由该构造函数创建的每个对象都有一个与其构造函数关联的隐式引用,即该对象的原型。此外,原型可能具有非null的隐式引用到其原型,以此类推;这称为原型链。

在基于类的面向对象语言中,通常状态由实例承载,方法由类承载,而继承仅用于结构和行为。在ECMAScript中,状态和方法由对象承载,而结构、行为和状态都是继承的。

原型是ECMAScript中用于实现结构、状态和行为继承的对象。当构造函数创建对象时,该对象隐式引用构造函数关联的原型以解析属性引用。程序表达式constructor.prototype可以引用构造函数的关联原型,添加到对象的原型的属性通过继承与共享原型的所有对象共享。


1

对于那些仍认为RFC比博客和基于观点的误解更重要的人,让我们试着回答一些问题来澄清一些观点。我不会重复之前回答中提到的所有正确差异,这里我只是试图通过总结rfc7159中的一些关键部分来增加价值。

https://www.rfc-editor.org/rfc/rfc7159中提取的内容:

JavaScript对象表示法(JSON)是一种用于序列化结构化数据的文本格式。它源自于JavaScript中的对象字面量,如ECMAScript编程语言标准第三版[ECMA-262]中所定义的那样。
JSON可以表示四种基本类型(字符串、数字、布尔值和null)和两种结构化类型(对象和数组)。
对象是零个或多个名称/值对的无序集合,其中名称是字符串,值可以是字符串、数字、布尔值、null、对象或数组。
begin-object = ws %x7B ws; {左花括号
end-object = ws %x7D ws; }右花括号
JSON值必须是对象、数组、数字或字符串,或者是以下三个文字名称之一:false null true 对象结构表示为一对花括号
对象内的名称应该是唯一的。
object = begin-object [member *(value-separator member)] end-object
所有名称都是唯一的对象在互操作性方面是可交互的,因为接收该对象的所有软件实现都将同意名称-值映射。当对象内的名称不唯一时,接收此类对象的软件的行为是不可预测的。
示例(来自RFC第12页)
这是一个JSON对象:
      {
        "Image": {
            "Width":  800,
            "Height": 600,
            "Title":  "View from 15th Floor",
            "Thumbnail": {
                "Url":    "http://www.example.com/image/481989943",
                "Height": 125,
                "Width":  100
            },
            "Animated" : false,
            "IDs": [116, 943, 234, 38793]
          }
      }

它的Image成员是一个对象,其缩略图成员是一个对象,其IDs成员是一个数字数组。

实际上并不存在"JSON对象"这种东西。

真的吗?


1
Davi,它不是一个“Object”,而是一个“String”。谢谢。 - abu abu

1

据我所知,主要区别在于灵活性

JSON是一种“JavaScript对象表示法”的包装器,它强制用户遵守更严格的规定来定义对象。它通过限制JavaScript对象表示法功能提供的可能的对象声明方式来实现这一点。

因此,我们拥有了更简单、更标准化的对象,更适合在平台之间进行数据交换。

因此,基本上,我的上面示例中的newObject是使用JavaScript对象表示法定义的一个对象;但它不是一个“有效”的JSON对象,因为它没有遵循JSON标准所要求的规则。

此链接也非常有帮助: http://msdn.microsoft.com/en-us/library/bb299886.aspx


2
JSON和对象表示法的目的完全不同:前者仅用于数据交换,而后者用于仅供内部使用的JS对象的创建。它们不是同一事物的更严格或更宽松的版本。 - ilyo

0

Javascript对象字面量 vs JSON:

  • 对象字面量语法是创建Javascript对象的一种非常方便的方式
  • JSON语言,代表“Javascript对象表示法”,其语法源自于Javascript对象字面量语法。它被用作一种独立于编程语言的文本数据传输格式。

例子:

JS对象表示法,在JS中用于在代码中方便地创建对象:

const JS_Object = {
  1: 2,  // the key here is the number 1, the value is the number 2
  a: 'b', // the key is the string a, the value is the string b
  func: function () { console.log('hi') }
  // the key is func, the value is the function
}

JSON 示例:

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    },
    "text": {
        "data": "Click Here",
        "size": 36,
        "style": "bold",
        "name": "text1",
        "hOffset": 250,
        "vOffset": 100,
        "alignment": "center",
        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
}}

主要区别:

  • JSON 中的所有对象键必须是字符串。在 JavaScript 中,对象键可以是字符串或数字。

  • JSON 中的所有字符串必须用“双引号”括起来。而在 JavaScript 中,单引号和双引号都可以使用。即使在 JavaScript 对象符号中没有引号,对象键也会被隐式转换为字符串。

  • 在 JSON 中,函数不能被定义为对象的值(因为这是特定于 JavaScript 的)。在 JavaScript 中,这完全合法。

Javascript 内置的 JSON 对象:

使用内置的 JSON 对象,JavaScript 提供了将 JSON 对象轻松转换为 JavaScript 对象,反之亦然。例如:

const Object = {
  property1: true,
  property2: false,
}; // creating object with JS object literal syntax

const JSON_object = JSON.stringify(Object);  // stringify JS object to a JSON string

console.log(JSON_object); // note that the (string) keys are in double quotes

const JS_object = JSON.parse(JSON_object);  // parse JSON string to JS object

console.log(JS_object.property1, JS_object.property2); 
// accessing keys of the newly created object


0

这里有一个令人惊讶的区别:您不能在JSON中使用undefined,所有值为未定义的对象字段在JSON.stringify之后都会消失

let object =  { "a": undefined } ;

let badJSON= '{ "a": undefined }';


console.log('valid JS object :', object );
console.log('JSON from object:', JSON.stringify(object) );
console.log('invalid json    :', JSON.parse(badJSON) );


0

首先,你应该知道什么是JSON:

它是一种与语言无关的数据交换格式。 JSON的语法受到JavaScript对象字面量表示法的启发,但它们之间存在一些差异。

例如,在JSON中,所有的键都必须加引号,而在对象字面量中则不需要:

// JSON: { "foo": "bar" }

// 对象字面量: var o = { foo: "bar" }; 在JSON中引号是必需的,因为在JavaScript中(更准确地说是在ECMAScript第3版中),禁止使用保留字作为属性名,例如:

var o = { if: "foo" }; // 在ES3中会导致语法错误 然而,将字符串字面量作为属性名(引用属性名)则没有问题:

var o = { "if": "foo" }; 所以为了“兼容性”(也许是为了方便eval函数?),引号是必需的。

JSON中的数据类型也受到限制,只能是以下值:

字符串 数字 对象 数组 字面量: true false null 字符串的语法有所改变。它们必须由双引号括起来,而在JavaScript中,你可以随意使用单引号或双引号。

// 无效的JSON: { "foo": 'bar' } 接受的JSON语法也发生了变化,在JavaScript中您可以使用十六进制字面量,例如0xFF或(臭名昭著的)八进制字面量,例如010。但在JSON中,您只能使用十进制字面量。

// 无效的JSON: { "foo": 0xFF }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接