【问题标题】:Parsing a json gives JSONDecodeError: Unterminated string解析 json 给出 JSONDecodeError: Unterminated string
【发布时间】:2021-07-07 10:00:05
【问题描述】:

我有一个带有换行符分隔 json 的文档,我在其中应用了一些功能。一切正常,直到这一行,它看起来就像这样:

{"_id": "5f114", "type": ["Type1", "Type2"], "company": ["5e84734"], "answers": [{"title": " answer 1", "value": false}, {"title": "answer 2
", "value": true}, {"title": "This is a title.", "value": true}, {"title": "This is another title", "value": true}], "audios": [null], "text": {}, "lastUpdate": "2020-07-17T06:24:50.562Z", "title": "This is a question?", "description": "1000 €.", "image": "image.jpg", "__v": 0}

整个代码:

import json  

def unimportant_function(d):
    d.pop('audios', None)
    return {k:v for k,v in d.items() if v != {}}


def parse_ndjson(data):
    return [json.loads(l) for l in data.splitlines()]

with open('C:\\path\\the_above_example.json', 'r', encoding="utf8") as handle:
    data = handle.read()
    dicts = parse_ndjson(data)

for d in dicts:
    new_d = unimportant_function(d)
    json_string=json.dumps(new_d, ensure_ascii=False)
    print(json_string)

错误JSONDecodeError: Unterminated string starting at: line 1 column 260 (char 259) 发生在dicts = parse_ndjson(data)。为什么?我也不知道“答案2”后面的那个符号是什么,它没有出现在数据中,但是当我复制粘贴它时它出现了。

数据有什么问题?

【问题讨论】:

  • 您可以尝试将true 更改为True 并将false 更改为False 吗? nullNone 相同,因为它们是 python 的预期关键字。
  • @JulesCivel 字符串是 JSON,因此它应该是 true 而不是 True 才能成为有效的 JSON。
  • 我尝试做json.loads('<the_JSON>'),它对我有用。我不知道如何重现错误。
  • “我也不知道“答案 2”后面的那个符号是什么”我在您粘贴的内容中没有看到任何不寻常的符号。
  • @KarlKnechtel 使用 json.loads() 时,字典包含:{'title': 'answer 2\u2029', 'value': True}\u2029 字符是我认为他在谈论的那个。

标签: python json dictionary parsing


【解决方案1】:

"answer 2"字符串中嵌入的不可打印字符是paragraph separator.splitlines()将其视为空格:

>>> 'foo\u2029bar'.splitlines()
['foo', 'bar']

(推测:ndjson 文件可能利用它来表示“这个字符串应该有一个换行符”,解决文件格式。如果是这样,它可能应该使用\n 转义。)

但是,如果您正常遍历文件的行,则不会对该字符进行特殊处理:

>>> # For demonstration purposes, I create a `StringIO`
>>> # from a hard-coded string. A file object reading
>>> # from disk will behave similarly.
>>> import io
>>> for line in io.StringIO('foo\u2029bar'):
...     print(repr(line))
...
'foo\u2029bar'

因此,简单的解决方法是让parse_ndjson 已经期待一系列行 - 不要调用.splitlines,并适当地修复调用代码。您可以直接传递开放的handle

def parse_ndjson(data):
    return [json.loads(l) for l in data]

with open('C:\\path\\the_above_example.json', 'r', encoding="utf8") as handle:
    dicts = parse_ndjson(handle)

或将其传递给list 以显式创建列表:

def parse_ndjson(data):
    return [json.loads(l) for l in data]

with open('C:\\path\\the_above_example.json', 'r', encoding="utf8") as handle:
    dicts = parse_ndjson(list(handle))

或使用提供的.readlines() 方法创建列表:

def parse_ndjson(data):
    return [json.loads(l) for l in data]

with open('C:\\path\\the_above_example.json', 'r', encoding="utf8") as handle:
    dicts = parse_ndjson(handle.readlines())

【讨论】:

  • 感谢您的解释!我现在明白问题出在代码中了。我知道这是一个愚蠢的问题,但是直接传递打开的句柄是否意味着我只是删除了 parse_ndjson 函数?
  • 这是正确的,提到如果复制代码 1:1 将不会有任何定义的“数据”名称,因为直接传递打开的句柄。我希望我可以编辑,但我不能:/
  • 错字(每次在with 块中,data 应该是handle)。固定。
猜你喜欢
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多