【问题标题】:How to load a json file with strings including double quotes (")如何加载包含双引号 (") 的字符串的 json 文件
【发布时间】:2017-04-20 00:46:57
【问题描述】:

我收到了大量 JSON 文件,我正在尝试将它们加载到 python 3.5 中

我已经做了一些清理工作,删除了双反斜杠和多余的引号,但是我遇到了一个我不知道如何解决的问题。

我正在运行以下代码:

with open(filepath,'r') as json_file:
    reader = json_file.readlines()
    for row in reader:
        row = row.replace('\\', '')
        row = row.replace('"{', '{')
        row = row.replace('}"', '}')
        response = json.loads(row)
        for i in response:
                responselist.append(i['ActionName']) 

但是它抛出了错误:

JSONDecodeError: Expecting ',' delimiter: line 1 column 388833 (char 388832)

导致问题的 JSON 部分是下面的状态文本条目:

"StatusId":8,
"StatusIdString":"UnknownServiceError",
"StatusText":"u003cCompany docTypeu003d"Mobile.Tile" statusIdu003d"421" statusTextu003d"Start time of 11/30/2015 12:15:00 PM is more than 5 minutes in the past relative to the current time of 12/1/2015 12:27:01 AM." copyrightu003d"Copyright Company Inc." versionNumberu003d"7.3" createdDateu003d"2015-12-01T00:27:01Z" responseIdu003d"e74710c0-dc7c-42db-b608-bf905d95d153" /u003e",
"ActionName":"GetTrafficTile"

我添加了换行符来说明我的观点,看起来python很不高兴字符串包含双引号。

我感觉这可能与我将 '\ \' 替换为 '' 弄乱了字符串中的 unicode 字符有关。有没有办法修复这些嵌套的字符串?我不介意 StatusText 字段是否被完全删除,我所追求的只是 ActionName 字段的列表。

编辑: 我在这里托管了一个示例文件:

https://www.dropbox.com/s/1oanrneg3aqandz/2015-12-01T00%253A00%253A42.527Z_2015-12-01T00%253A01%253A17.478Z?dl=0

这与我收到的完全一样,在我替换多余的反斜杠和引号之前

这是一个包含一个错误条目的示例的精简版本

["{\"apiServerType\":0,\"RequestId\":\"52a65260-1637-4653-a496-7555a2386340\",\"StatusId\":0,\"StatusIdString\":\"Ok\",\"StatusText\":null,\"ActionName\":\"GetCameraImage\",\"Url\":\"http://mosi-prod.cloudapp.net/api/v1/GetCameraImage?AuthToken=vo*AB57XLptsKXf0AzKjf1MOgQ1hZ4BKipKgYl3uGew%7C&CameraId=13782\",\"Lat\":0.0,\"Lon\":0.0,\"iVendorId\":12561,\"iConsumerId\":2986897,\"iSliverId\":51846,\"UserId\":\"2986897\",\"HardwareId\":null,\"AuthToken\":\"vo*AB57XLptsKXf0AzKjf1MOgQ1hZ4BKipKgYl3uGew|\",\"RequestTime\":\"2015-12-01T00:00:42.5278699Z\",\"ResponseTime\":\"2015-12-01T00:01:02.5926127Z\",\"AppId\":null,\"HttpMethod\":\"GET\",\"RequestHeaders\":\"{\\\"Connection\\\":[\\\"keep-alive\\\"],\\\"Via\\\":[\\\"HTTP/1.1 nycnz01msp1ts10.wnsnet.attws.com\\\"],\\\"Accept\\\":[\\\"application/json\\\"],\\\"Accept-Encoding\\\":[\\\"gzip\\\",\\\"deflate\\\"],\\\"Accept-Language\\\":[\\\"en-us\\\"],\\\"Host\\\":[\\\"mosi-prod.cloudapp.net\\\"],\\\"User-Agent\\\":[\\\"Traffic/5.4.0\\\",\\\"CFNetwork/758.1.6\\\",\\\"Darwin/15.0.0\\\"]}\",\"RequestContentHeaders\":\"{}\",\"RequestContentBody\":\"\",\"ResponseBody\":null,\"ResponseContentHeaders\":\"{\\\"Content-Type\\\":[\\\"image/jpeg\\\"]}\",\"ResponseHeaders\":\"{}\",\"MiniProfilerJson\":null}"]

【问题讨论】:

  • 如果它是 json,你不应该删除任何东西。如果你已经删除了反斜杠......不是那些用来转义现在给你带来问题的引号的反斜杠吗? json 是故意放入这些注释的。如果您最终不喜欢解码,则可能是向 json 编码器传递的任何内容中存在错误。
  • 如何发布一个示例 json 文件以便我们自己查看。
  • 我添加了一个指向我收到的文件示例的链接
  • 我的答案中的代码是您正在寻找的,还是我误解了您的问题?

标签: json python-3.x double-quotes


【解决方案1】:

问题与您想象的有些不同。无论程序构建这些文件,都使用已经 json 编码的数据,并最终对某些信息进行双重甚至三重编码。我在 shell 会话中将其剥离并获得了可用的 python 数据。你可以(1)去吸毒打谁写了这个程序,构建了这个热气腾腾的一堆......嗯......善良? (2) 手动扫描并解码内部 json 字符串。

我解码了数据,它是一个字符串列表,但这些字符串看起来很像 json

>>> data = json.load(open('test.json'))
>>> type(data)
<class 'list'>
>>> d0 = data[0]
>>> type(d0)
<class 'str'>
>>> d0[:70]
'{"apiServerType":0,"RequestId":"52a65260-1637-4653-a496-7555a2386340",'

果然可以解码

>>> d0_1 = json.loads(d0)
>>> type(d0_1)
<class 'dict'>
>>> d0_1
{'ResponseBody': None, 'StatusText': None, 'AppId': None, 'ResponseTime': '2015-12-01T00:01:02.5926127Z', 'HardwareId': None, 'RequestTime': '2015-12-01T00:00:42.5278699Z', 'StatusId': 0, 'Lon': 0.0, 'Url': 'http://mosi-prod.cloudapp.net/api/v1/GetCameraImage?AuthToken=vo*AB57XLptsKXf0AzKjf1MOgQ1hZ4BKipKgYl3uGew%7C&CameraId=13782', 'RequestContentBody': '', 'RequestId': '52a65260-1637-4653-a496-7555a2386340', 'MiniProfilerJson': None, 'RequestContentHeaders': '{}', 'ActionName': 'GetCameraImage', 'StatusIdString': 'Ok', 'HttpMethod': 'GET', 'iSliverId': 51846, 'ResponseHeaders': '{}', 'ResponseContentHeaders': '{"Content-Type":["image/jpeg"]}', 'apiServerType': 0, 'AuthToken': 'vo*AB57XLptsKXf0AzKjf1MOgQ1hZ4BKipKgYl3uGew|', 'iConsumerId': 2986897, 'RequestHeaders': '{"Connection":["keep-alive"],"Via":["HTTP/1.1 nycnz01msp1ts10.wnsnet.attws.com"],"Accept":["application/json"],"Accept-Encoding":["gzip","deflate"],"Accept-Language":["en-us"],"Host":["mosi-prod.cloudapp.net"],"User-Agent":["Traffic/5.4.0","CFNetwork/758.1.6","Darwin/15.0.0"]}', 'iVendorId': 12561, 'Lat': 0.0, 'UserId': '2986897'}

选择其中一个条目,看起来更像 json

>>> hdrs = d0_1['RequestHeaders']
>>> type(hdrs)
<class 'str'>

是的,它可以解码为我想要的内容

>>> hdrs_0 = json.loads(hdrs)
>>> type(hdrs_0)
<class 'dict'>
>>> 
>>> hdrs_0["Via"]
['HTTP/1.1 nycnz01msp1ts10.wnsnet.attws.com']
>>> 
>>> type(hdrs_0["Via"])
<class 'list'>

【讨论】:

  • 如果他们还在这家公司,他们现在会受到如此多的打击。问题是我要查看大约 8000 个这些文件,因此手动扫描字符串是不可行的。我可以设置一个 try 语句通过第二次解码来处理异常吗?
  • 这些文件可能遵循一种模式,一旦你找到了一个模式,你就拥有了它们。否则,我会完全按照你的想法去做。遍历所有列表和字典,测试值是否为字符串,然后尝试json.loads(value)。你会得到一个 json.decoder.JSONDecodeError 用于真正应该保留字符串的字符串。
  • 我发现所有不可读的文件都具有相同的 actionName,而我所追求的只是不同响应类型的计数。我设置了一个记录失败次数的尝试循环,并将其附加到我的结果中。我已将此答案标记为正确的见解。
【解决方案2】:

你来了:):

responselist = []
with open('dataFile.json','r') as json_file:
    reader = json_file.readlines()
    for row in reader:
        strActNm = 'ActionName":"'; lenActNm = len(strActNm)
        actionAt = row.find(strActNm)
        while actionAt > 0:
            nxtQuotAt = row.find('"',actionAt+lenActNm+2)
            responselist.append( row[actionAt-1: nxtQuotAt+1] )
            actionAt = row.find('ActionName":"', nxtQuotAt)
print(responselist)

给出:

>python3.6 -u "dataFile.py"
['"ActionName":"GetTrafficTile"']
>Exit code: 0

其中dataFile.json 是包含您提供的行的文件,dataFile.py 是上面提供的代码。

这是一个艰难的旅程,但如果文件格式不正确,您必须找到解决方法,并且在任何情况下都可以使用简单的模式匹配。对于更复杂的情况,您将需要正则表达式(正则表达式),但在这种情况下,一个简单的.find() 就足以完成这项工作。

代码还在该行中找到多个“动作”(如果该行包含多个动作)。

这是您在链接中提供的文件的结果,同时对上面的代码进行了以下小修改:

responselist = []
with open('dataFile1.json','r') as json_file:
    reader = json_file.readlines()
    for row in reader:
        strActNm='\\"ActionName\\":\\"'
        # strActNm = 'ActionName":"'
        lenActNm = len(strActNm)
        actionAt = row.find(strActNm)
        while actionAt > 0:
            nxtQuotAt = row.find('"',actionAt+lenActNm+2)
            responselist.append( row[actionAt: nxtQuotAt+1].replace('\\','') )
            actionAt = row.find('ActionName":"', nxtQuotAt)
print(responselist)

给予:

>python3.6 -u "dataFile.py"
['"ActionName":"GetCameraImage"']
>Exit code: 0

其中 dataFile1.json 是您在链接中提供的文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 2019-01-22
    • 2017-01-26
    • 2020-03-17
    • 1970-01-01
    • 2021-12-27
    相关资源
    最近更新 更多