3

我无法使用 jsonlines 解析请求的正文。我使用 tornado 作为服务器,这发生在 post() 方法中。我这样做的目的是将请求的主体解析为单独的 JSON,然后使用 jsonlines Reader 对其进行迭代,对每一个进行一些工作,然后将它们推送到数据库。我通过将 utf-8 编码的主体转储到一个文件中解决了这个问题,然后使用:

with jsonlines.open("temp.txt") as reader:

这对我行得通。我可以遍历整个文件

for obj in reader:

我只是觉得这是一个不必要的开销,如果我能理解是什么让我不能只使用这段代码,那么可以减少它:

log = self.request.body.decode("utf-8")
with jsonlines.Reader(log) as reader:
   for obj in reader:

我得到的例外是:

jsonlines.jsonlines.InvalidLineError:行包含无效的 json:期望用双引号括起来的属性名称:第 1 行第 2 列(字符 1)(第 1 行)

我试过在这里搜索这个错误,我发现的只是人们尝试使用格式不正确的 json 的例子,这些 json 有一个引号而不是双引号。对我来说不是这样。我调试了请求,发现从 decode 方法返回的字符串确实有属性和值的双引号。

这是我发送的请求正文的示例(这是 Postman 中的样子):

{"type":"event","timestamp":"2018-03-25 09:19:50.999","event":"ButtonClicked","params":{"screen":"MainScreen","button":"SettingsButton"}} 
{"type":"event","timestamp":"2018-03-25 09:19:51.061","event":"ScreenShown","params":{"name":"SettingsScreen"}} 
{"type":"event","timestamp":"2018-03-25 09:19:53.580","event":"ButtonClicked","params":{"screen":"SettingsScreen","button":"MissionsButton"}} 
{"type":"event","timestamp":"2018-03-25 09:19:53.615","event":"ScreenShown","params":{"name":"MissionsScreen"}}

您可以通过在 post 方法中使用这段简单的代码并发送我通过 Postman 提供的行来重现异常:

log = self.request.body.decode("utf-8")
with jsonlines.Reader(log) as currentlog:
    for obj in currentlog:
        print("obj")

作为旁注:邮递员将数据作为文本发送,而不是 JSON。

如果您需要更多信息来回答这个问题,请告诉我。我注意到的一件事是从 decode 方法返回的字符串以一个引号开始和结束。我猜这是因为 JSON 本身中的双引号。它有什么关系吗?一个例子:

'{"type":"event","timestamp":"2018-03-25 09:19:50.999","event":"ButtonClicked","params":{"screen":"MainScreen","button":"SettingsButton"}}'

谢谢你的帮助!

4

1 回答 1

3

jsonlines.Reader接受 iterable 作为 arg (“第一个参数必须是产生 JSON 编码字符串的可迭代”,而不是像您的示例中那样 json 编码的单个字符串),但是,在 之后.decode("utf-8"),log 将是一个字符串,它恰好支持 iterable界面。因此,当阅读器在后台调用时next(log),它将获得日志字符串的第一项,即字符{,并将尝试将其作为 json 行处理,这显然是无效的。log = log.split()在将日志传递给阅读器之前尝试。

于 2018-04-10T14:59:15.243 回答