【问题标题】:Using Python's json.loads with JSON containing regex value, breaks?将 Python 的 json.loads 与包含正则表达式值的 JSON 一起使用,会中断吗?
【发布时间】:2019-05-30 10:26:27
【问题描述】:

TL,DR; 如何使用 Python's JSON decoder 加载包含带有转义反斜杠的正则表达式的 JSON?

Detail;正则表达式\\[0-9]\\将匹配(例如):

\2\

同样的正则表达式可以编码为 JSON 值:

{
  "pattern": "\\[0-9]\\"
}

反过来,JSON 值可以在 Python 中编码为字符串(注意单引号):

'{"pattern": "\\[0-9]\\"}'

在 Python 中加载 JSON 时,会引发 JSONDecodeError

import json
json.loads('{"pattern": "\\[0-9]\\"}')

问题是由正则表达式转义黑斜线引起的:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Invalid \escape: line 1 column 14 (char 13)
>>> json.loads('{"pattern": "\\[0-9]\\"}')

这让我感到惊讶,因为每一步似乎都很合理(即有效的正则表达式、有效的 JSON 和有效的 Python)。

如何使用 Python's JSON decoder 加载包含带有转义反斜杠的正则表达式的 JSON?

【问题讨论】:

  • json.loads(r'{"pattern": "\\[0-9]\\"}')
  • 你的 实际 JSON 是什么?你的字符串文字不正确,但无论你加载什么都应该是。
  • 什么是正则表达式错误?

标签: python json regex


【解决方案1】:

发生的事情是 Python 首先将输入转义为 loads 作为字符串文字,使其成为 '{"pattern": "\[0-9]\"}'(双反斜杠 -> 单反斜杠)。然后,loads 现在尝试转义 \[,这是无效的。要修复,请再次转义反斜杠。但是,将其指定为原始字符串更容易且更实用:

>>> import json
>>> json.loads('{"pattern": "\\[0-9]\\"}')
json.decoder.JSONDecodeError: Invalid \escape: line 1 column 14 (char 13)
>>> json.loads(r'{"pattern": "\\[0-9]\\"}')
{'pattern': '\\[0-9]\\'} # No error

请注意,如果从文件加载,此问题将不适用。

test.json:

{"pattern": "\\[0-9]\\"}

Python:

import json

with open('test.json', 'r') as infile:
    json.load(infile) # no problem

基本上,问题在于您传入字符串 literal,但具有讽刺意味的是,您的字符串 literal 并没有被 literal .

【讨论】:

  • 如果不使用原始语法怎么办?
  • @sln: 再次转义反斜杠:'{"pattern": "\\\\[0-9]\\\\"}'
  • @sln 我的意思是,您可以使用'{"pattern": "\\\\[0-9]\\\\"}',但特别是如果您从外部来源获取 json 字符串,原始语法会更好。
  • 那么在python中单引号字符串与双引号字符串一样吗?其中'\n' 是回车符?
  • @Jack 我应该措辞更好,我的意思是 Python 处理字符串文字中的转义序列。例如,将\n 替换为换行符,将\t 替换为制表符等。
【解决方案2】:

r 表示该字符串将被视为原始字符串,这意味着所有转义码都将被忽略:

json.loads(r'{"pattern": "\\[0-9]\\"}')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    • 2016-12-29
    • 2011-06-19
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多