JavaScript JSON.parse “0x”字符串奇怪的转换

huangapple go评论84阅读模式
英文:

Javascript JSON.parse "0x" string strange conversion

问题

{
"data": {
"artemis_ids": {},
"symbols": {
"0XBTC": {
"price": 2.37
}
}
}
}

When I use JSON.parse in Google apps script, the "0XBTC" string is somehow converted to number 11. See below the results of console.log:

console.log("content", content);
console.log("content json", JSON.parse(content));

英文:

I have the following json structure returned by an API:

{
    "data": {
        "artemis_ids": {},
        "symbols": {
            "0XBTC": {
                "price": 2.37
            }
        }
    }
}

When I use JSON.parse in Google apps script, the "0XBTC" string is somehow converted to number 11. See below the results of console.log:

console.log("content", content);
console.log("content json", JSON.parse(content));

JavaScript JSON.parse “0x”字符串奇怪的转换

Any idea why this is happening and how to solve it?

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

var content = `
    {
        &quot;data&quot;: {
            &quot;artemis_ids&quot;: {},
            &quot;symbols&quot;: {
                &quot;0XBTC&quot;: {
                    &quot;price&quot;: 2.37
                }
            }
        }
    }
`;

console.log(&quot;content&quot;, content);
console.log(&quot;content json&quot;, JSON.parse(content));

<!-- end snippet -->

答案1

得分: 2

以下是您要翻译的内容:

Modification points:

From content json {data={artemis_ids={}, symbols={11={price=2.37}}}}, your showing log, I guessed that you might disable the V8 runtime with the script editor. But, when the V8 runtime is disabled, the backticks cannot be used. From this situation, also I guessed that your showing snippet might not be your actual script.

By supposing that my guess is correct, I tested the following sample script. And, I disabled the V8 runtime with the script editor.

function myFunction() {
  var content = '{ "data": { "artemis_ids": {}, "symbols": { "0XBTC": { "price": 2.37 } } } }';

  console.log("content", content);
  console.log("content json", JSON.parse(content));
}

When this script is run without V8 runtime, the following result is obtained.

JavaScript JSON.parse “0x”字符串奇怪的转换

I confirmed that console.log("content json", JSON.parse(content)) shows content json {data={artemis_ids={}, symbols={11={price=2.37}}}}. If my guess is correct, I think that this might be the reason for your current issue.

And also, when I tested the following script.

function sample() {
  var content = '{ "data": { "artemis_ids": {}, "symbols": { "0XBTC": { "price": 2.37 } } } }';

  var sample1 = JSON.stringify(JSON.parse(content));
  var sample2 = Object.keys(JSON.parse(content).data.symbols);

  console.log(sample1);
  console.log(sample2);
}

console.log(sample1) and console.log(sample2) are as follows.

{ "data": { "artemis_ids": {}, "symbols": { "11": { "price": 2.37 } } } }

and

[11]

From this situation, I guessed that this situation might be a bug or the current specification of Google Apps Script without V8 runtime. But, in the current stage, when the V8 runtime is disabled with the script editor, "runtimeVersion": "DEPRECATED_ES5" is added to the manifest file (appsscript.json). Ref

In order to avoid this situation, as a simple solution, please enable V8 runtime with the script editor. Ref

JavaScript JSON.parse “0x”字符串奇怪的转换

By this, the above script sample() returns as follows.

{ "data": { "artemis_ids": {}, "symbols": { "0XBTC": { "price": 2.37 } } } }

and

[ '0XBTC' ]

0XBTC is correctly used as the key.

Note:

If you are required to use your script by disabling the V8 runtime, how about using polyfill of JSON.parse? Ref When this is reflected in a sample script, it becomes as follows.


function sample2() {
  // Ref: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#%E3%83%9D%E3%83%AA%E3%83%95%E3%82%A3%E3%83%AB
  var rx_one = /^[\],:{}\s]*$/;
  var rx_two = /\\(?:[&quot;\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  var rx_three = /&quot;[^&quot;\\\n\r]*&quot;|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
  var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
  var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
  JSON.parse = function (text, reviver) {

    // The parse method takes a text and an optional reviver function, and returns
    // a JavaScript value if the text is a valid JSON text.

    var j;

    function walk(holder, key) {

      // The walk method is used to recursively walk the resulting structure so
      // that modifications can be made.

      var k;
      var v;
      var value = holder[key];
      if (value && typeof value === "object") {
        for (k in value) {
          if (Object.prototype.hasOwnProperty.call(value, k)) {
            v = walk(value, k);
            if (v !== undefined) {
              value[k] = v;
            } else {
              delete value[k];
            }
          }
        }
      }
      return reviver.call(holder, key, value);
    }

    // Parsing happens in four stages. In the first stage, we replace certain
    // Unicode characters with escape sequences. JavaScript handles many characters
    // incorrectly, either silently deleting them, or treating them as line endings.

    text = String(text);
    rx_dangerous.lastIndex = 0;
    if (rx_dangerous.test(text)) {
      text = text.replace(rx_dangerous, function (a) {
        return (
          "\\u" +
          ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
        );
      });
    }

    // In the second stage, we run the text against regular expressions that look
    // for non-JSON patterns. We are especially concerned with "()()()" and "new"
    // because they can cause invocation, and "=" because it can cause mutation.
    // But just to be safe, we want to reject all unexpected forms.

    // We split the second stage into 4 regexp operations in order to work around
    // crippling inefficiencies in IE's and Safari's regexp engines. First we
    // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
    // replace all simple value tokens with "]" characters. Third, we delete all
    // open brackets that follow a colon or comma or that begin the text. Finally,
    // we look to see that the remaining characters are only whitespace or "]" or
    // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

    if (
      rx_one
英文:

Modification points:

From content json {data={artemis_ids={}, symbols={11={price=2.37}}}}, your showing log, I guessed that you might disable the V8 runtime with the script editor. But, when the V8 runtime is disabled, the backticks cannot be used. From this situation, also I guessed that your showing snippet might not be your actual script.

By supposing that my guess is correct, I tested the following sample script. And, I disabled the V8 runtime with the script editor.

function myFunction() {
  var content = &#39;{&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;0XBTC&quot;:{&quot;price&quot;:2.37}}}}&#39;;

  console.log(&quot;content&quot;, content);
  console.log(&quot;content json&quot;, JSON.parse(content));
}

When this script is run without V8 runtime, the following result is obtained.

JavaScript JSON.parse “0x”字符串奇怪的转换

I confirmed that console.log(&quot;content json&quot;, JSON.parse(content)) shows content json {data={artemis_ids={}, symbols={11={price=2.37}}}}. If my guess is correct, I think that this might be the reason for your current issue.

And also, when I tested the following script.

function sample() {
  var content = &#39;{&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;0XBTC&quot;:{&quot;price&quot;:2.37}}}}&#39;;

  var sample1 = JSON.stringify(JSON.parse(content));
  var sample2 = Object.keys(JSON.parse(content).data.symbols);

  console.log(sample1);
  console.log(sample2);
}

console.log(sample1) and console.log(sample2) are as follows.

{&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;11&quot;:{&quot;price&quot;:2.37}}}}

and

[11]

From this situation, I guessed that this situation might be a bug or the current specification of Google Apps Script without V8 runtime. But, in the current stage, when the V8 runtime is disabled with the script editor, &quot;runtimeVersion&quot;: &quot;DEPRECATED_ES5&quot; is added to the manifest file (appsscript.json). Ref

In order to avoid this situation, as a simple solution, please enable V8 runtime with the script editor. Ref

JavaScript JSON.parse “0x”字符串奇怪的转换

By this, the above script sample() returns as follows.

{&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;0XBTC&quot;:{&quot;price&quot;:2.37}}}}

and

[ &#39;0XBTC&#39; ]

0XBTC is correctly used as the key.

Note:

If you are required to use your script by disabling the V8 runtime, how about using polyfill of JSON.parse? Ref When this is reflected in a sample script, it becomes as follows.

<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

function sample2() {
  // Ref: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#%E3%83%9D%E3%83%AA%E3%83%95%E3%82%A3%E3%83%AB
  var rx_one = /^[\],:{}\s]*$/;
  var rx_two = /\\(?:[&quot;\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  var rx_three = /&quot;[^&quot;\\\n\r]*&quot;|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
  var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
  var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
  JSON.parse = function (text, reviver) {

    // The parse method takes a text and an optional reviver function, and returns
    // a JavaScript value if the text is a valid JSON text.

    var j;

    function walk(holder, key) {

      // The walk method is used to recursively walk the resulting structure so
      // that modifications can be made.

      var k;
      var v;
      var value = holder[key];
      if (value &amp;&amp; typeof value === &quot;object&quot;) {
        for (k in value) {
          if (Object.prototype.hasOwnProperty.call(value, k)) {
            v = walk(value, k);
            if (v !== undefined) {
              value[k] = v;
            } else {
              delete value[k];
            }
          }
        }
      }
      return reviver.call(holder, key, value);
    }

    // Parsing happens in four stages. In the first stage, we replace certain
    // Unicode characters with escape sequences. JavaScript handles many characters
    // incorrectly, either silently deleting them, or treating them as line endings.

    text = String(text);
    rx_dangerous.lastIndex = 0;
    if (rx_dangerous.test(text)) {
      text = text.replace(rx_dangerous, function (a) {
        return (
          &quot;\\u&quot; +
          (&quot;0000&quot; + a.charCodeAt(0).toString(16)).slice(-4)
        );
      });
    }

    // In the second stage, we run the text against regular expressions that look
    // for non-JSON patterns. We are especially concerned with &quot;()&quot; and &quot;new&quot;
    // because they can cause invocation, and &quot;=&quot; because it can cause mutation.
    // But just to be safe, we want to reject all unexpected forms.

    // We split the second stage into 4 regexp operations in order to work around
    // crippling inefficiencies in IE&#39;s and Safari&#39;s regexp engines. First we
    // replace the JSON backslash pairs with &quot;@&quot; (a non-JSON character). Second, we
    // replace all simple value tokens with &quot;]&quot; characters. Third, we delete all
    // open brackets that follow a colon or comma or that begin the text. Finally,
    // we look to see that the remaining characters are only whitespace or &quot;]&quot; or
    // &quot;,&quot; or &quot;:&quot; or &quot;{&quot; or &quot;}&quot;. If that is so, then the text is safe for eval.

    if (
      rx_one.test(
        text
          .replace(rx_two, &quot;@&quot;)
          .replace(rx_three, &quot;]&quot;)
          .replace(rx_four, &quot;&quot;)
      )
    ) {

      // In the third stage we use the eval function to compile the text into a
      // JavaScript structure. The &quot;{&quot; operator is subject to a syntactic ambiguity
      // in JavaScript: it can begin a block or an object literal. We wrap the text
      // in parens to eliminate the ambiguity.

      j = eval(&quot;(&quot; + text + &quot;)&quot;);

      // In the optional fourth stage, we recursively walk the new structure, passing
      // each name/value pair to a reviver function for possible transformation.

      return (typeof reviver === &quot;function&quot;) ?
        walk({
          &quot;&quot;: j
        }, &quot;&quot;) :
        j;
    }

    // If the text is not JSON parsable, then a SyntaxError is thrown.

    throw new SyntaxError(&quot;JSON.parse&quot;);
  };


  var content = &#39;{&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;0XBTC&quot;:{&quot;price&quot;:2.37}}}}&#39;;

  var sample1 = JSON.stringify(JSON.parse(content));
  var sample2 = Object.keys(JSON.parse(content).data.symbols);

  console.log(sample1); // &lt;--- {&quot;data&quot;:{&quot;artemis_ids&quot;:{},&quot;symbols&quot;:{&quot;0XBTC&quot;:{&quot;price&quot;:2.37}}}}
  console.log(sample2); // &lt;--- [0XBTC]
}

sample2();

<!-- end snippet -->

References:

答案2

得分: -1

我认为这不是一个代码问题,因为它在node@18和Chrome@latest上运行良好。

JavaScript JSON.parse “0x”字符串奇怪的转换

英文:

I think it is not a code issue, because it runs well at node@18 and Chrome@latest.

JavaScript JSON.parse “0x”字符串奇怪的转换

huangapple
  • 本文由 发表于 2023年7月27日 23:12:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定