V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shaoyaoju
V2EX  ›  程序员

JSON Lines

  •  
  •   shaoyaoju ·
    juzhiyuan · 2019-10-27 00:12:36 +08:00 · 2889 次点击
    这是一个创建于 1858 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文: https://blog.shaoyaoju.org/json-lines/

    JSON Lines 是一种文本格式,适用于存储大量结构相似的嵌套数据、在协程之间传递信息等。

    例子如下:

    {"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
    {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]}
    {"name": "May", "wins": []}
    {"name": "Deloise", "wins": [["three of a kind", "5♣"]]}
    

    它有如下特点:

    1. 每一行都是完整、合法的 JSON 值;采用 \n 或 \r\n 作为行分隔符;
    2. 采用 UTF-8 编码;
    3. 使用 jsonl 作为文件扩展名;建议使用 gzip 或 bzip2 压缩并生成 .jsonl.gz 或 .jsonl.bz2 文件,以便节省空间。

    对比

    // CSV
    
    id,father,mother,children
    1,Mark,Charlotte,1
    2,John,Ann,3
    3,Bob,Monika,2
    
    // JSON
    
    [
       {
          "id": 1,
          "father": "Mark",
          "mother": "Charlotte",
          "children": 1
       },
       {
          "id": 2,
          "father": "John",
          "mother": "Ann",
          "children": 3
       },
       {
          "id": 3,
          "father": "Bob",
          "mother": "Monika",
          "children": 2
       }
    ]
    

    对于同样的数据内容,CSV 比 JSON 更简洁,但却不易读。此外,CSV 无法表示嵌套数据,例如一个家庭下全部成员的名字,但 JSON 却可以很容易地表示出来:

    {
      "familyMembers": ["JuZhiyuan", "JuShouChang"]
    }
    

    既然 JSON 如此灵活,那为何还需要 JSON Lines 呢?

    考虑如下场景:一个大小为 1GB 的 JSON 文件,当我们需要读取 /写入内容时,需要读取整个文件、存储至内存并将其解析、操作,这是不可取的。

    若采用 JSON Lines 保存该文件,则操作数据时,我们无需读取整个文件后再解析、操作,而可以根据 JSON Lines 文件中每一行便为一个 JSON 值 的特性,边读取边解析、操作。例如:在插入 JSON 值时,我们只需要 append 值到文件中即可。

    因此,操作 JSON Lines 文件时,只需要:

    1. 读取一行值;
    2. 将值解析为 JSON ;
    3. 重复 1、2 步骤。 那么如何将 JSON Lines 转换为 JSON 格式呢?下方代码为 JavaScript 示例:
    const jsonLinesString = `{"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
    {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]}
    {"name": "May", "wins": []}
    {"name": "Deloise", "wins": [["three of a kind", "5♣"]]}`;
    
    const jsonLines = jsonLinesString.split(/\n/);
    const jsonString = "[" + jsonLines.join(",") + "]";
    const jsonValue = JSON.parse(jsonString);
    
    console.log(jsonValue);
    

    参考

    1. JSON Lines
    2. JSON Lines format: Why jsonl is better than a regular JSON for web scraping
    8 条回复    2019-10-27 10:00:38 +08:00
    CEBBCAT
        1
    CEBBCAT  
       2019-10-27 01:06:52 +08:00
    感谢写文介绍,之前都没有听说过,应该是适合日志类的数据吧?看样子只能分拆首层 list,需要和 JSON 结构相配合

    个人觉得楼主写了不少冤枉字,同等信息量我觉得三分之二的字就能说明白,还更清晰。一开始还以为是楼主发明了这个结构呢。
    CEBBCAT
        2
    CEBBCAT  
       2019-10-27 01:09:01 +08:00
    @CEBBCAT #1 简单来说就是例子举的有点早,要是我我会想简单讲讲结构,再举例子。而且后面那个 family 例子也不够“生动”,children 我差点以为是外键。
    CEBBCAT
        3
    CEBBCAT  
       2019-10-27 01:10:30 +08:00
    @CEBBCAT #2 不好意思再追加一下,我觉得直接简单讲讲和 JSON 的区别,优缺点,再上一份代码大家就都明白了。后边代码非常“Show me the code”
    optional
        4
    optional  
       2019-10-27 01:31:51 +08:00 via Android
    但是对于相同数据结构的数据,浪费了大量的字符来表示字段名
    nvkou
        5
    nvkou  
       2019-10-27 07:40:37 +08:00 via Android
    非杠 但这个场景我估计不会用 json 来传输了
    ptyfork
        6
    ptyfork  
       2019-10-27 07:50:35 +08:00
    早就开始用这个东西了,而且还不知道已经有人提出来了。
    以为自己是第一个人发明的,后来一查原来别人早就在用了,😂,而且还有了详细的文档。
    因为 json 用多了,在数据量非常大的时候,想到这个是个非常自然的东西。
    AlohaV2
        7
    AlohaV2  
       2019-10-27 07:51:52 +08:00 via iPhone
    这个跟 BSON 比优势在哪儿呢
    momocraft
        8
    momocraft  
       2019-10-27 10:00:38 +08:00
    有壓縮時 field 重複不是大問題
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1295 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 23:24 · PVG 07:24 · LAX 15:24 · JFK 18:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.