为什么 ruby 的 JSON 解析器会吃掉我的反斜杠?
Why does ruby's JSON parser eat my backslash?
以下JSON格式的例子包含一个反斜杠,如果我运行 JSON.load
,反斜杠消失:
JSON.load('{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }')
# => {"88694"=>{ "regex"=>".*?. (CVE-2015-46055)"}}
如何保留反斜杠?
我的目标是拥有这个结构,每当我需要时,读取文件,将 JSON 加载到 Hash 中,然后搜索那些正则表达式。
更新 1
这是我想要的例子。
irb> "stack.overflow"[/.*?\./]
=> "stack."
我 不能 将正则表达式从 JSON 传递到我的字符串以捕获“.”,因为“\”消失。
str = '{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }'
#=> "{ \"88694\": { \"regex\": \".*?\. (CVE-2015-46055)\" } }"
str.chars
#=> ["{", " ", "\"", "8", "8", "6", "9", "4", "\"", ":", " ", "{", " ",
# "\"", "r", "e", "g", "e", "x", "\"", ":", " ", "\"", ".", "*", "?",
# "\", ".",
# ~~~ ~~
# " ", "(",..., "}", " ", "}"]
这向我们表明 str
确实包含一个反斜杠字符后跟一个句点。原因是 str
被单引号括起来了。如果 str
包含在双引号中,\.
只会被视为转义句点:
"{ '88694': { 'regex': '.*?\. (CVE-2015-46055)' } }".chars[25,3]
#=> ["?", ".", " "]
str
的return值将单引号字符串转换为双引号字符串:
"{ \"88694\": { \"regex\": \".*?\. (CVE-2015-46055)\" } }"
\
是一个反斜杠字符后跟一个句点。使用双引号现在可以转义句点,但它前面没有反斜杠,只有退格符。
现在让我们添加另一个反斜杠,看看会发生什么:
str1 = '{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }'
str1.chars == str.chars
#=> true
结果是一样的。这是因为单引号支持转义序列 \
(单反斜杠)(并且只有一个:\'
[单引号])。
现在让我们添加第三个反斜杠:
str2 = '{ "88694": { "regex": ".*?\\. (CVE-2015-46055)" } }'
str2.chars
#=> ["{", " ", "\"", "8", "8", "6", "9", "4", "\"", ":", " ", "{", " ",
# "\"", "r", "e", "g", "e", "x", "\"", ":", " ", "\"", ".", "*", "?",
# "\", "\", ".",
# ~~~~ ~~~~ ~~~
# " ", "(",..., "}", " ", "}"]
惊讶? \
生成一个反斜杠字符(单引号中的转义反斜杠),\
生成第二个反斜杠字符(单引号中的反斜杠),.
是单引号中的句点。
我们得到:
s = {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}.to_json
JSON.parse(str)
#=> {"88694"=>{"regex"=>".*?. (CVE-2015-46055)"}}
JSON.parse(str1)
#=> {"88694"=>{"regex"=>".*?. (CVE-2015-46055)"}}
JSON.parse(str2)
#=> {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}}
str2
就是我们想要的,如
JSON.parse(str2)["88694"]["regex"].chars[2,4]
#=> ["?", "\", ".", " "]
我们也可以逆向工作:
js = {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}}.to_json
#=> "{\"88694\":{\"regex\":\".*?\\. (CVE-2015-46055)\"}}"
'{"88694":{"regex":".*?\\. (CVE-2015-46055)"}}' == js
#=> true
此字符串与 str2
在引号子字符串外的所有空格都被删除后相同。
JSON 似乎将两个连续的反斜杠字符视为一个反斜杠字符。请参阅@Jordan 的评论。
也许 reader 可以详细说明 JSON 在这里做什么。
以下JSON格式的例子包含一个反斜杠,如果我运行 JSON.load
,反斜杠消失:
JSON.load('{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }')
# => {"88694"=>{ "regex"=>".*?. (CVE-2015-46055)"}}
如何保留反斜杠?
我的目标是拥有这个结构,每当我需要时,读取文件,将 JSON 加载到 Hash 中,然后搜索那些正则表达式。
更新 1
这是我想要的例子。
irb> "stack.overflow"[/.*?\./]
=> "stack."
我 不能 将正则表达式从 JSON 传递到我的字符串以捕获“.”,因为“\”消失。
str = '{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }'
#=> "{ \"88694\": { \"regex\": \".*?\. (CVE-2015-46055)\" } }"
str.chars
#=> ["{", " ", "\"", "8", "8", "6", "9", "4", "\"", ":", " ", "{", " ",
# "\"", "r", "e", "g", "e", "x", "\"", ":", " ", "\"", ".", "*", "?",
# "\", ".",
# ~~~ ~~
# " ", "(",..., "}", " ", "}"]
这向我们表明 str
确实包含一个反斜杠字符后跟一个句点。原因是 str
被单引号括起来了。如果 str
包含在双引号中,\.
只会被视为转义句点:
"{ '88694': { 'regex': '.*?\. (CVE-2015-46055)' } }".chars[25,3]
#=> ["?", ".", " "]
str
的return值将单引号字符串转换为双引号字符串:
"{ \"88694\": { \"regex\": \".*?\. (CVE-2015-46055)\" } }"
\
是一个反斜杠字符后跟一个句点。使用双引号现在可以转义句点,但它前面没有反斜杠,只有退格符。
现在让我们添加另一个反斜杠,看看会发生什么:
str1 = '{ "88694": { "regex": ".*?\. (CVE-2015-46055)" } }'
str1.chars == str.chars
#=> true
结果是一样的。这是因为单引号支持转义序列 \
(单反斜杠)(并且只有一个:\'
[单引号])。
现在让我们添加第三个反斜杠:
str2 = '{ "88694": { "regex": ".*?\\. (CVE-2015-46055)" } }'
str2.chars
#=> ["{", " ", "\"", "8", "8", "6", "9", "4", "\"", ":", " ", "{", " ",
# "\"", "r", "e", "g", "e", "x", "\"", ":", " ", "\"", ".", "*", "?",
# "\", "\", ".",
# ~~~~ ~~~~ ~~~
# " ", "(",..., "}", " ", "}"]
惊讶? \
生成一个反斜杠字符(单引号中的转义反斜杠),\
生成第二个反斜杠字符(单引号中的反斜杠),.
是单引号中的句点。
我们得到:
s = {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}.to_json
JSON.parse(str)
#=> {"88694"=>{"regex"=>".*?. (CVE-2015-46055)"}}
JSON.parse(str1)
#=> {"88694"=>{"regex"=>".*?. (CVE-2015-46055)"}}
JSON.parse(str2)
#=> {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}}
str2
就是我们想要的,如
JSON.parse(str2)["88694"]["regex"].chars[2,4]
#=> ["?", "\", ".", " "]
我们也可以逆向工作:
js = {"88694"=>{"regex"=>".*?\. (CVE-2015-46055)"}}.to_json
#=> "{\"88694\":{\"regex\":\".*?\\. (CVE-2015-46055)\"}}"
'{"88694":{"regex":".*?\\. (CVE-2015-46055)"}}' == js
#=> true
此字符串与 str2
在引号子字符串外的所有空格都被删除后相同。
JSON 似乎将两个连续的反斜杠字符视为一个反斜杠字符。请参阅@Jordan 的评论。
也许 reader 可以详细说明 JSON 在这里做什么。