使用未转义的双引号进行JSON解码

时间:2019-05-20 11:54:18

标签: python json

请参阅以下来自源的响应JSON。 Source不能灵活地进行更改。挑战在于在“结果”中解码键值对。

{"result":"{\"key1\" : \"value with \"n,a.\".\" , \"key2\":\"value with \"n.a.\".\" }"}

结果中嵌套的JSON:

{"key1" : "value with "n,a."." , "key2":"value with "n.a."."}

我正在使用python进行解码。

json_string = '{\"result\":\"{\\"key1\\" : \\"value with \\"n,a.\\".\\" , \\"key2\\":\\"value with \\"n.a.\\".\\"}\"}'

#The following string with no double quotes within value part works as expected
#json_string = '{\"result\":\"{\\"key1\\" : \\"value with n,a.\\" , \\"key2\\":\\"value with n.a. .\\"}\"}'

data1 = json.loads(json_string)

data1['result']
# '{"key1" : "value with "n,a."." , "key2":"value with "n.a."."}'

data_dict_string = data1['result']
json_stringp = "[{0}]".format(data_dict_string)
data_list = json.loads(json_stringp)

双引号如预期那样会导致以下错误,

JSONDecodeError: Expecting ',' delimiter: line 1 column 25 (char 24)

如何在JSON的值部分中删除双引号?

2 个答案:

答案 0 :(得分:3)

编辑:可能会有一个实际的解决方案,详细说明如下。

他们的JSON绝对被破坏了,在正常情况下,这不应该由您来解决。

没有安全的方法来纠正这种损坏,因为如您所见,当转义符被剥夺时,信息会丢失,因此结果是模棱两可的:

"{\"abc\": \"def\": \"ghi\"}"可能表示"{\"abc\": \"def\\": \\"ghi\"}"(值是def": "ghi)或"{\"abc\\": \\"def\": \"ghi\"}"(键是abc": "def

如果数据结构相当简单并且不包含任何其他问题,则可以应用一些启发式方法。

例如,如果结构是扁平的并且键都是字母数字,则可以尝试识别潜在的键(/(\{|\\", )\\"([a-z]+)\\": \\"/),然后尝试将它们之间/之后的内容解析为值。

如果可能存在嵌套对象(如果任何字符串包含进一步错误编码的JSON,就更不用说了),它将变得更加复杂。

基本上,这超出了“缺陷”的范围-您正在尝试在此处解读鸡蛋。


附录:在计算机科学方面,我认为从技术上讲可以描述该问题,甚至可以解决该问题(即枚举可能被解码的候选结构)从给定的字符串中选出,希望是少数几个,然后您可以进一步验证以找到正确的字符串)。 JSON由context-free grammar描述,删除转义符会将其转换为ambiguous grammar(即,具有多个语法树的语法会产生相同的字符串)。有解析算法可以在(最坏的)立方时间O(n ^ 3)中处理该问题。

据我所知,GNU Bison实现了此解析器,并且可以作为Python库使用:http://freenet.mcnabhosting.com/python/pybison/

因此,如果您没有其他选择,并且可以将“残破的JSON”的语法形式化,那么最终可能是最健壮(但也很复杂)的方法。

答案 1 :(得分:0)

此问题使用枚举器解决。共享指向“答案”解决方案的链接 Replace escaped double quotes to single quotes in Python using regex

解决方案代码:

import json
js = r'{"result":"{\"key\":\"How are you? \"Great!\" he said. \"Coffee ?\"\"},{\"key\":\" 2. \"Why not, sure.\". They walked away\"}"}'

data1 = json.loads(js)
s = data1['result']

good_characters = [":","{","}",","]
result = "" 

for key, value in enumerate(s):

    if ((value == "\"" and s[key-1] not in good_characters) and (value == "\"" and s[key+1] not in good_characters) or (value == "\"" and s[key-1] == "," and s[key-2] != "\"")):
        result += '\''   
    else:
        result += value        
#print(result)
json_string = "[{0}]".format(result)
data_list = json.loads(json_string)
print(data_list)