英文:
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));
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 = `
{
"data": {
"artemis_ids": {},
"symbols": {
"0XBTC": {
"price": 2.37
}
}
}
}
`;
console.log("content", content);
console.log("content json", 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.
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
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 = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|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 = '{"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.
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
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.
<!-- 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 = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|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.test(
text
.replace(rx_two, "@")
.replace(rx_three, "]")
.replace(rx_four, "")
)
) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" 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("(" + text + ")");
// 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 === "function") ?
walk({
"": j
}, "") :
j;
}
// If the text is not JSON parsable, then a SyntaxError is thrown.
throw new SyntaxError("JSON.parse");
};
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); // <--- {"data":{"artemis_ids":{},"symbols":{"0XBTC":{"price":2.37}}}}
console.log(sample2); // <--- [0XBTC]
}
sample2();
<!-- end snippet -->
References:
答案2
得分: -1
我认为这不是一个代码问题,因为它在node@18和Chrome@latest上运行良好。
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论