为什么 Python 不能用转义引号解码这个有效的 JSON?



我有一个JSON里面有一些类似JSON的东西:

TEST_LINE = """Oct 21 22:39:28 GMT [TRACE] (Carlos-288) org.some.awesome.LoggerFramework RID=8e9076-4dd9-ec96-8f35-bde193498f: {
"service": "MyService",
"operation": "queryShowSize",
"requestID": "8e9076-4dd9-ec96-8f35-bde193498f",
"timestamp": 1634815968000,
"parameters": [
{
"__type": "org.some.awsome.code.service#queryShowSizeRequest",
"externalID": {
"__type": "org.some.awsome.code.common#CustomerID",
"value": "48317"
},
"CountryID": {
"__type": "org.some.awsome.code.common#CountryID",
"value": "125"
},
"operationOriginalDate": 1.63462085667E9,
"operationType": "MeasureWithToes",
"measureInstrumentIdentifier": "595909-48d2-6115-85e8-b3aa7b"
}
],
"output": {
"__type": "org.some.awsome.code.common#queryShowSizeReply",
"shoeSize": {
"value": "$ion_1_0 'org.some.awsome.model.processing.ShoeMeasurementBI@1.0'::'org.some.awsome.model.processing.FeetScience@1.0'::{customer_id:"983017317",measureInstrumentIdentifierTilda:"595909-48d2-6115-85e8-b3aa7b",foot_owner:"Oedipus",toe_code:"LR2X10",account_number_token:"1234-2838316-1298470",token_status:VALID,country_code:GRC,measure_store_format:METRIC}"
}
}
}
"""

正则表达式给了我JSON的开始,我尝试从那里解码。根据https://jsonlint.com/,在该点之后是有效的JSON。

那么为什么Python的JSON模块不解码呢?我得到这个错误:

Exception has occurred: JSONDecodeError
Expecting ',' delimiter: line 25 column 156 (char 992)
File "/Users/decoder/Downloads/json-problem.py", line 44, in read_json
d = json.loads(line)
^^^^^^^^^^^^^^^^
File "/Users/decoder/Downloads/json-problem.py", line 48, in <module>
print(read_json(TEST_LINE))
^^^^^^^^^^^^^^^^^^^^
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 25 column 156 (char 992)

第25行,第156个字符指向output.shoeSize.value中的第一个"

但是为什么呢?该嵌入值只是大致JSON,但它应该尝试解码它,因为它是作为一个普通字符串给出的。并且引号被很好地转义以避免提前结束字符串。

FIND_JSON = re.compile(
r"w{3} d{2} (d{2}[: ]){3}GMT [[^]]+] ([^)]+) "
r"org.some.awesome.LoggerFramework RID=[^:]+: "
)
def read_json(line: str) -> str | None:
if not (m := FIND_JSON.match(line)):
return None
line = line[m.end(0) :]
d = json.loads(line)
return d

print(read_json(TEST_LINE))

我也尝试过raw_decode(),但同样失败。我不明白。

更新1:对于指向非转义双引号的评论者,我没有看到它。对我来说,冒号之后是反斜杠,然后是双引号。再说一次,对我来说,我觉得很好。有副本吗?粘贴转换发生在SO上?

更新2:添加了使问题变得明显的(仍然缺失的)代码。

它不是100%清楚你是如何定义字符串的,但问题很可能是引号的转义正在被python处理,并在它被馈送到json库之前被删除:

data ="""{
"value": "{customer_id:"983017317"..."
}'
"""
print(data)  

打印:

{
"value": "{customer_id:"983017317"..."
}'

看到转义已经消失。要让python不处理转义并由json处理,您需要将其声明为r"your_string"的原始字符串即

data =r"""{
"value": "{customer_id:"983017317"..."
}"""
print(data)

打印:

{
"value": "{customer_id:"983017317"..."
}

,然后你可以把它输入json.loads(),没有任何问题。

您遇到的问题是因为在"shoeSize"key包含单引号('),在JSON中没有正确转义。JSON标准只考虑双引号(")作为有效的字符串分隔符,并且您嵌入的字符串混合了单引号和双引号。

要使JSON有效并可被Python的JSON模块解码,您可以将"shoeSize"中的单引号替换为转义的双引号价值。这是"shoesize"的修改版本。键-值对:


"shoeSize": {
"value": "$ion_1_0 \"org.some.awsome.model.processing.ShoeMeasurementBI@1.0\"::\"org.some.awsome.model.processing.FeetScience@1.0\"::{customer_id:\"983017317\",measureInstrumentIdentifierTilda:\"595909-48d2-6115-85e8-b3aa7b\",foot_owner:\"Oedipus\",toe_code:\"LR2X10\",account_number_token:\"1234-2838316-1298470\",token_status:VALID,country_code:GRC,measure_store_format:METRIC}"
}

做了这些修改后,你应该能够使用Python的JSON模块解码JSON:


import json
# Assuming modified_json contains the modified JSON string
d = json.loads(modified_json)

最新更新