[英]Are all JSON strings also syntactically valid Python string literals?
我正在寫一個 JavaScript function 生成一個 Python 程序。 我可以在字符串上使用 JavaScript 的JSON.stringify()
並每次都期望有效的 Python 字符串嗎?或者是否存在意味着我必須編寫自己的toPythonString()
function 的邊緣情況?
最簡潔的答案是不。
長答案在實踐中是肯定的。 幾乎。 不同之處在於 JSON 字符串可以有正斜杠反斜杠轉義。 因此字符串"\/"
被 JSON (和 JavaScript)解釋為單個正斜杠'/'
但作為反斜杠后跟正斜杠 Python '\\/'
。
但是,在 JSON 中以這種方式序列化正斜杠不是強制性的。 如果您可以控制 JSON 序列化程序並且可以確保它不會反斜杠轉義正斜杠,那么您的 JSON 字符串應該始終是有效的 ZA7F5F35426B927411FC9231B5638 字符串。
查看V8中 JSON 序列化程序的源代碼(Google Chrome 和 Node.js 的 JavaScript 引擎),它總是將'/'
序列化為"/"
,正如您所期望的那樣。
JSON 字符串語法記錄在json.org和 Python 字符串語法記錄在其文檔的詞匯分析部分。
We can see that a regular JSON string character is "Any codepoint except "
, \
or control characters" whereas Python string characters are "Any source character except \
or newline or the quote". Since newline is a control character, this means JSON is比 Python 更嚴格,這很好。那么問題是“任何代碼點”和“任何源字符”之間的重疊是什么?我不知道如何回答,但我猜它們可能是相同的, assuming both the JSON and Python are encoded in UTF-8. (If you're interested in JavaScript strings instead of JSON strings, then JavaScript is generally encoded in UTF-16, so there could be some incompatibilities arising from that here.)
我們還看到 JSON 有一些反斜杠轉義,除了一個轉義的正斜杠\/
之外,Python 都支持這些轉義。 這是 Python 不共享的 JSON 字符串的一部分。
最后,在 JSON 中,我們可以使用\uXXXX
語法來轉義任何字符,Python 也支持這一點。
如果你想在 JavaScript 中序列化一個字符串為 Python 的源碼,可以這樣做:
const regexSingleEscape = /'|\\|\p{C}|\p{Z}/gu;
const regexDoubleEscape = /"|\\|\p{C}|\p{Z}/gu;
function asPythonStr(s) {
let quote = "'";
if (s.includes("'") && !s.includes('"')) {
quote = '"';
}
const regex = quote === "'" ? regexSingleEscape : regexDoubleEscape;
return (
quote +
s.replace(regex, (c: string): string => {
switch (c) {
case " ":
return " ";
case "\x07":
return "\\a";
case "\b":
return "\\b";
case "\f":
return "\\f";
case "\n":
return "\\n";
case "\r":
return "\\r";
case "\t":
return "\\t";
case "\v":
return "\\v";
case "\\":
return "\\\\";
case "'":
case '"':
return "\\" + c;
}
const hex = (c.codePointAt(0) as number).toString(16);
if (hex.length <= 2) {
return "\\x" + hex.padStart(2, "0");
}
if (hex.length <= 4) {
return "\\u" + hex.padStart(4, "0");
}
return "\\U" + hex.padStart(8, "0");
}) +
quote
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.