首页 > 解决方案 > 解析 json 给出 JSONDecodeError: Unterminated string

问题描述

我有一个带有换行符分隔 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”之后的那个符号是什么,它没有出现在数据中,但是当我复制粘贴它时它出现了。

数据有什么问题?

标签: pythonjsondictionaryparsing

解决方案


嵌入在"answer 2"字符串中的不可打印字符是段落分隔符,它被视为空格.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直接通过 open :

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())

推荐阅读