【问题标题】:Python conversion from JSON to JSONL从 JSON 到 JSONL 的 Python 转换
【发布时间】:2016-12-19 07:17:21
【问题描述】:

我希望将标准 JSON 对象操作为一个对象,其中每一行都必须包含一个单独的、自包含的有效 JSON 对象。见JSON Lines

JSON_file =

[{u'index': 1,
  u'no': 'A',
  u'met': u'1043205'},
 {u'index': 2,
  u'no': 'B',
  u'met': u'000031043206'},
 {u'index': 3,
  u'no': 'C',
  u'met': u'0031043207'}]

To JSONL:

{u'index': 1, u'no': 'A', u'met': u'1043205'}
{u'index': 2, u'no': 'B', u'met': u'031043206'}
{u'index': 3, u'no': 'C', u'met': u'0031043207'}

我当前的解决方案是将 JSON 文件作为文本文件读取,并从开头删除 [ 并从末尾删除 ]。因此,在每一行上创建一个有效的 JSON 对象,而不是包含行的嵌套对象。

我想知道是否有更优雅的解决方案?我怀疑在文件上使用字符串操作可能会出错。

动机是将json文件读入Spark上的RDD。查看相关问题 - Reading JSON with Apache Spark - `corrupt_record`

【问题讨论】:

  • 这不是有效的 JSON 输入,也不是有效的 JSON 输出。您在此处处理 Python 对象,而不是 JSON 序列化。即使您的输出是有效的 JSON,它也不是有效的 JSONL,因为您有 尾随逗号
  • 另外,如果输出中的对象是有效的 JSON,则不会有尾随逗号。

标签: python json


【解决方案1】:

jsonlines 包完全适合您的用例:

import jsonlines

items = [
    {'a': 1, 'b': 2},
    {'a', 123, 'b': 456},
]
with jsonlines.open('output.jsonl', 'w') as writer:
    writer.write_all(items)

(是的,我是在您发布原始问题多年后写的。)

【讨论】:

  • items 是一个列表
【解决方案2】:

一个简单的方法是在终端中使用jq 命令。

在 Debian 及其衍生产品上安装 jq

$ sudo apt-get install jq

CentOS/RHEL 用户应该运行:

$ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ sudo yum install jq -y

基本用法:

$ jq -c '.[]' some_json.json >> output.jsonl

如果您需要处理大文件,我强烈建议使用--stream 标志。这将使jq 以流模式解析您的 json。

$ jq -c --stream '.[]' some_json.json >> output.json

但是,如果您需要在 python 文件中执行此操作,您可以使用 bigjson,这是一个有用的库,可以在流模式下解析 JSON:

$ pip3 install bigjson

要读取一个巨大的 json(在我的例子中是 40 GB):

import bigjson

# Reads json file in streaming mode
with open('input_file.json', 'rb') as f:
    json_data = bigjson.load(f)

    # Open output file  
    with open('output_file.jsonl', 'w') as outfile:
        # Iterates over input json
        for data in json_data:
            # Converts json to a Python dict  
            dict_data = data.to_python()
            
            # Saves the output to output file
            outfile.write(json.dumps(dict_data)+"\n")

如果您愿意,请尝试并行化此代码以提高性能。在这里发布结果:)

文档和源代码:https://github.com/henu/bigjson

【讨论】:

  • 到目前为止,此答案仅适用于 Debian 及其衍生产品。是否有其他操作系统的其他可能安装说明?
  • 是的,但是很长,所以,请按照此链接在 RHEL/CentOS 上安装:cyberithub.com/…
【解决方案3】:

您的输入似乎是一系列 Python 对象;它肯定不是有效的 JSON 文档。

如果你有一个 Python 字典列表,那么你所要做的就是将每个条目分别转储到一个文件中,然后是一个换行符:

import json

with open('output.jsonl', 'w') as outfile:
    for entry in JSON_file:
        json.dump(entry, outfile)
        outfile.write('\n')

json 模块的默认配置是输出不嵌入换行符的 JSON。

假设您的 ABC 名称确实是字符串,则会产生:

{"index": 1, "met": "1043205", "no": "A"}
{"index": 2, "met": "000031043206", "no": "B"}
{"index": 3, "met": "0031043207", "no": "C"}

如果您从包含条目列表的 JSON 文档开始,只需先使用 json.load()/json.loads() 解析该文档。

【讨论】:

    猜你喜欢
    • 2021-08-21
    • 1970-01-01
    • 2022-01-23
    • 2019-01-17
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    • 2018-07-20
    相关资源
    最近更新 更多