JSON 和 JSONL 的区别

发布于:2025-02-10 ⋅ 阅读:(48) ⋅ 点赞:(0)

一、JSON 和 JSONL 的区别

1. JSON 格式

  • 全称: JavaScript Object Notation

  • 结构: JSON 是一种树状嵌套结构,整个文件是一个完整的 JSON 对象。

  • 特点:

    1. 文件中通常只有一个 JSON 对象。
    2. 数据可以嵌套,例如对象中包含数组,数组中包含对象。
    3. 适用于需要表示复杂数据关系的场景。
  • 示例:

[
    {
        "id": 1,
        "name": "Alice",
        "age": 25
    },
    {
        "id": 2,
        "name": "Bob",
        "age": 30
    }
]

2. JSONL 格式

  • 全称: JSON Lines

  • 结构: JSONL 是一个轻量化的格式,每行表示一个独立的 JSON 对象。

  • 特点:

    1. 数据是逐行存储的,每行是一个完整的 JSON 对象。
    2. 文件中的每行可以独立解析,彼此没有嵌套关系。
    3. 适用于需要流式处理或者分布式处理的场景(如日志处理、数据批量加载)。
  • 示例:

{"id": 1, "name": "Alice", "age": 25}
{"id": 2, "name": "Bob", "age": 30}

主要区别

特性 JSON JSONL
存储方式 整体是一个完整的 JSON 对象 每行是一个 JSON 对象
读取方式 一次性读取整个文件 可以逐行读取和解析
嵌套支持 可以嵌套复杂结构 每行独立,通常不嵌套
处理场景 适合一次性加载的应用 适合流式、分布式处理场景
文件大小影响 文件越大,加载越慢 可以按行加载,处理更高效

使用场景

  1. JSON:

    • 配置文件
    • 小规模数据存储
    • 描述复杂结构的层次化数据
  2. JSONL:

    • 大规模数据处理
    • 日志文件存储
    • 数据流应用(例如机器学习训练数据)

选择建议

  • 文件较小:优先使用 JSON,便于读取和管理。
  • 文件较大:优先使用 JSONL,可以逐行加载,避免内存占用过高。
  • 日志处理/分布式处理:使用 JSONL,每行可以独立处理,适合流式计算。

如果有具体的数据需求或处理场景,可以告诉我,我可以给出更针对性的建议!


3. JSON 和 JSONL 保存方法

# 保存为 json 格式文件
output_stats_file = 'data.jsonl'
with open(output_stats_file, 'w', encoding='utf-8') as outfile:
    json.dump(results, outfile, ensure_ascii=False, indent=2)
# 保存为 jsonl 格式文件
output_stats_file = 'data.jsonl'
with open(output_stats_file, 'w', encoding='utf-8') as outfile:
    for result in results:
        json.dump(result, outfile, ensure_ascii=False)
        outfile.write('\n')

二、加载文件方式

1. with open 加载

# 加载 JSON 文件
with open(data_path, 'r', encoding='utf-8') as f:
    data = json.load(f)

# 加载 JSONL 文件
with open(data_path, 'r', encoding='utf-8') as f:
    data = [json.loads(line.strip()) for line in f]

2. Hugging Face datasets 库加载

from datasets import load_dataset

# 加载 JSON 数据
dataset = load_dataset("json", data_files="path_to_your_file.json")

# 加载 JSONL 数据
dataset = load_dataset("json", data_files="path_to_your_file.jsonl")

# 加载多个 JSON 文件
data_files = {
    "train": "path_to_train.json",
    "test": "path_to_test.json",
}
dataset = load_dataset("json", data_files=data_files)

# dataset的其他用法
dataset = dataset.select(range(5))

# 训练集和验证集比例划分
train_ratio = 0.9
split_dataset = dataset.train_test_split(test_size = 1 - train_ratio)
train_dataset = split_dataset["train"]
eval_dataset = split_dataset["test"]

# 数据预处理函数: 将每个数据转化为 input_ids、labels、attention_mask
def tokenize_function(examples):
    return tokenizer(
        # examples["input"] + examples["output"],
        examples["input"]
        padding="max_length",
        truncation=True,
        max_length=max_seq_length,
    )

# tokenizer分词获取 input_ids、labels、attention_mask
train_dataset = train_dataset.map(tokenize_function, batched=True, remove_columns=["input", "output"])
eval_dataset = eval_dataset.map(tokenize_function, batched=True, remove_columns=["input", "output])

# 省略中间代码 ………………

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    data_collator=data_collator,
)

输出如下: 

Generating train split: 3 examples [00:00, 429.49 examples/s]
DatasetDict({
    train: Dataset({
        features: ['input', 'output'],
        num_rows: 3
    })
})