JSON.parse和JSON.stringify不是幂等的,这是不好的

这个问题是多方面的 -

(1a)JSON是JavaScript的基础,那么为什么没有JSON类型? JSON类型将是一个格式为JSON的字符串。 它会被标记为解析/字符串化,直到数据被更改。 只要数据发生变化,它就不会被标记为JSON,并且需要重新分析/重新串联。

(1b)在一些软件系统中,不可能(意外地)试图通过网络发送一个普通的JS对象而不是一个序列化的JS对象? 为什么不试图避免呢?

(1c)为什么我们不能直接在一个JavaScript对象上调用JSON.parse ,而不是先将其字符串化呢?

    var json = {   //JS object in properJSON format
        "baz":{
            "1":1,
            "2":true,
            "3":{}
        }
    };

    var json0 = JSON.parse(json); //will throw a parse error...bad...it should not throw an error if json var is actually proper JSON.

所以我们别无选择,只能这样做:

 var json0= JSON.parse(JSON.stringify(json));

但是,有一些不一致之处,例如:

JSON.parse(true); //works
JSON.parse(null); //works
JSON.parse({}); //throws error

(2)如果我们在同一个对象上继续调用JSON.parse ,最终会抛出一个错误。 例如:

var json = {   //same object as above
    "baz":{
        "1":1,
        "2":true,
        "3":{}
    }
};

var json1 = JSON.parse(JSON.stringify(json));
var json2 = JSON.parse(json1); //throws an error...why

(3)为什么JSON.stringify无限地在输入中添加越来越多的斜杠? 它不仅难以读取调试结果,而且实际上会使您处于危险状态,因为一个JSON.parse调用不会返回一个普通的JS对象,您必须多次调用JSON.parse才能找回纯JS的对象。 这很糟糕,意味着在给定的JS对象上多次调用JSON.stringify是非常危险的。

   var json = {
        "baz":{
            "1":1,
            "2":true,
            "3":{}
        }
    };

    var json2 = JSON.stringify(json);
    console.log(json2);

    var json3 = JSON.stringify(json2);
    console.log(json3);

    var json4 = JSON.stringify(json3);
    console.log(json4);

    var json5 = JSON.stringify(json4);
    console.log(json5); 

(4)函数的名称是什么,我们应该能够反复调用而不改变结果(IMO如何处理JSON.parseJSON.stringify )? 这个最好的术语似乎是“幂等的”,你可以在评论中看到。

(5)考虑到JSON是一种可用于网络对象的序列化格式,在某些情况下,您不能调用JSON.parseJSON.stringify两次或甚至一次,而不会引发一些问题,这似乎完全疯狂。 为什么会这样?

如果您正在为Java,JavaScript或任何语言发明下一个序列化格式,请考虑此问题。

国际海事组织应该有两个国家为一个给定的对象。 一个序列化状态和一个反序列化状态。 在具有更强类型系统的软件语言中,这通常不是问题。 但在JavaScript中使用JSON时,如果在同一对象上调用JSON.parse两次,则会遇到致命异常。 同样,如果我们在同一个对象上调用两次JSON.stringify,我们可能会陷入不可恢复的状态。 就像我说的应该只有两个状态和两个状态,普通的JS对象和序列化的JS对象。


1)JSON.parse需要一个字符串,你给它一个Javascript对象。

2)与第一个类似的问题。 您将一个字符串提供给需要对象的函数。

3)Stringfy实际上期望一个字符串,但是你给它一个String对象。 因此,它将采用与第一个字符串相同的措施来避免引号和斜线。 因此,该语言可以理解引号,字符串内的其他特殊字符。

4)你可以为此编写自己的函数。

5)因为您正在尝试进行非法转换。 这与第一个和第二个问题有关。 只要提供正确的对象类型,就可以多次调用它。 唯一的问题是额外的斜线,但它实际上是标准。


我们将从您创建的这个噩梦开始:字符串输入和整数输出。
IJSON.parse(IJSON.stringify("5")); //=> 5

内置的JSON函数不会以这种方式让我们失败:字符串输入和字符串输出。
JSON.parse(JSON.stringify("5")); //=> "5"

JSON必须保留您的原始数据类型

JSON.stringify成一个函数,把数据包装在一个盒子里,把JSON.parse作为把它从盒子里拿出来的函数。

考虑以下:

var a = JSON.stringify;
var b = JSON.parse;

var data = "whatever";

b(a(data)) === data; // true

b(b(a(a(data)))) === data; // true

b(b(b(a(a(a(data)))))) === data; // true

也就是说,如果我们将数据放在3个框中,我们必须从3个框中取出。 对?

如果我将数据放在2个框中并从1中删除,那么我还没有保存我的数据,我持有一个包含我的数据的框。 对?

b(a(a(data))) === data; // false

对我来说似乎理智......


  • JSON.parse解开你的数据。 如果它没有装箱,它不能解开它。 JSON.parse需要一个字符串输入,并且给它一个JavaScript对象字面值

  • JSON.parse的第一个有效调用将返回一个对象。 在这个对象输出上再次调用JSON.parse将导致与#1相同的失败

  • 反复调用JSON.stringify会多次“ JSON.stringify ”我们的数据。 所以当然你必须重复调用JSON.parse然后才能从每个“盒子”中获取数据

  • 幂等

  • 不,这是完全理智的。 你不能三重印戳。

    你永远不会犯这样的错误,对吧?

    var json = IJSON.stringify("hi");
    IJSON.parse(json);
    //=> "hi"
    

    好吧,那是幂等的,但那又如何

    var json = IJSON.stringify("5");
    IJSON.parse(json);
    //=> 5
    

    UH OH! 我们每次给它一个字符串,但第二个例子返回一个整数。 输入数据类型已丢失!

    JSON函数会在这里失败吗?

    var json = JSON.stringify("hi");
    JSON.parse(json);
    //=> "hi"
    

    都好。 那么"5"呢?

    var json = JSON.stringify("5");
    JSON.parse(json));
    //=> "5"
    

    耶,类型已被预先保存! JSON作品, IJSON不。


  • 也许一个更真实的例子:

    好的,所以你有很多开发人员在忙着应用程序。 它会对您的基础数据的类型做出鲁莽的假设。 假设这是一个聊天应用程序,它可以在消息从点到点的过程中进行多次转换。

    一路上你会有:

  • IJSON.stringify
  • 数据移动通过网络
  • IJSON.parse
  • 另一个IJSON.parse是因为谁在乎? 它是幂等的,对吗?
  • String.prototype.toUpperCase - 因为这是一个格式选择
  • 让我们看看这些消息

    bob: 'hi'
    // 1) '"hi"', 2) <network>, 3) "hi", 4) "hi", 5) "HI"
    

    Bob的消息看起来很好。 我们来看看Alice的。

    alice: '5'
    // 1) '5'
    // 2) <network>
    // 3) 5
    // 4) 5
    // 5) Uncaught TypeError: message.toUpperCase is not a function
    

    不好了! 服务器刚刚崩溃。 你会注意到它甚至不是IJSON.parse的重复调用,在这里失败了。 即使你曾经叫过它,它也会失败。

    似乎你从一开始就注定要死去......诅咒鲁莽的开发者和他们粗心的数据处理!

    如果Alice使用任何发生的也是有效的JSON的输入,它将会失败

    alice: '{"lol":"pwnd"}'
    // 1) '{"lol":"pwnd"}'
    // 2) <network>
    // 3) {lol:"pwnd"}
    // 4) {lol:"pwnd"}
    // 5) Uncaught TypeError: message.toUpperCase is not a function
    

    好吧,不公平的例子也许吧? 你在想,“我不是那么鲁莽,我不会在这样的用户输入上调用IJSON.stringifyIJSON.parse !” 没关系。 您从根本上破坏了JSON,因为原始类型不能再提取。

    如果我使用IJSON一个字符串,然后取消它,谁知道我会回来? 当然不是你,当然不是开发者使用你的鲁莽功能。

  • “我会收回一个字符串吗?”
  • “我会得到一个整数吗?”
  • “也许我会得到一个对象?”
  • “也许我会得到蛋糕,我希望它是蛋糕”
  • 这是不可能告诉的!

    你处在一个全新的痛苦世界中,因为你从一开始就对你的数据类型一直不小心。 你的类型很重要,所以请小心处理它们。

    JSON.stringify需要一个对象类型,JSON.parse需要一个字符串类型

    现在你看到光了吗?


    我会试着给你一个理由,说明为什么JSON.parse不能在没有问题的情况下在同一个数据上被多次调用。

    你可能不知道它,但一个JSON文件不一定是一个对象。

    这是一个有效的JSON文档:

    "some text"
    

    让我们将这个文档的表示存储在一个javascript变量中:

    var JSONDocumentAsString = '"some text"';
    

    并努力工作:

    var JSONdocument = JSON.parse(JSONDocumentAsString);
    JSONdocument === 'some text';
    

    这会导致错误,因为这个字符串不是JSON文档的表示

    JSON.parse(JSONdocument);
    // SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
    

    在这种情况下怎么可能有JSON.parse猜测JSONdocument (作为一个字符串)是一个JSON文档,它应该已经回到它不变?

    链接地址: http://www.djcxy.com/p/40667.html

    上一篇: JSON.parse and JSON.stringify are not idempotent and that is bad

    下一篇: How to JSON.stringify and JSON.parse without getting an empty object?