如何通过node.js中JSONStream模块解析一个大的、以换行符分隔的JSON文件?

yvfmudvl  于 2023-05-28  发布在  Node.js
关注(0)|答案(5)|浏览(281)

我有一个很大的json文件,它是以换行符分隔的JSON,其中多个标准JSON对象由额外的换行符分隔,例如。

{'name':'1','age':5}
{'name':'2','age':3}
{'name':'3','age':6}

我现在在node.js中使用JSONStream来解析一个大的json文件,我使用JSONStream的原因是因为它是基于流的。
但是,示例中的两种解析语法都不能帮助我解析每行都包含分隔JSON的json文件

var parser = JSONStream.parse(**['rows', true]**);
var parser = JSONStream.parse([**/./**]);

有人能帮我吗

6kkfgxo0

6kkfgxo01#

警告:自从这个答案被写出来后,JSONStream库的作者removed the emit root event functionality,显然是为了修复一个内存泄漏。如果您需要emit root功能,您可以使用0.x.x版本。
以下为未修改的原始答案

来自自述文件:

JSONStream.parse(path)

path应该是属性名、RegExps、布尔值和/或函数的数组。任何与路径匹配的对象都将以'data'的形式发出。
当接收到所有数据时,将发出'root'事件。'root'事件传递根对象&匹配对象的计数。
在您的例子中,由于您希望返回JSON对象而不是特定的属性,因此您将使用'root'事件,并且不需要指定路径。
你的代码可能看起来像这样:

var fs = require('fs'),
    JSONStream = require('JSONStream');

var stream = fs.createReadStream('data.json', {encoding: 'utf8'}),
    parser = JSONStream.parse();

stream.pipe(parser);

parser.on('root', function (obj) {
  console.log(obj); // whatever you will do with each JSON object
});
mwecs4sa

mwecs4sa2#

JSONstream用于解析单个巨大的JSON对象,而不是许多JSON对象。您希望在换行符处拆分流,然后将其解析为JSON。
NPM包split声称可以进行这种拆分,甚至有一个特性可以为您解析JSON行。

cu6pst1q

cu6pst1q3#

如果您的文件不够大,这里有一个简单但不高性能的解决方案:

const fs = require('fs');

let rawdata = fs.readFileSync('fileName.json');

let convertedData = String(rawdata)
    .replace(/\n/gi, ',')
    .slice(0, -1);

let JsonData= JSON.parse(`[${convertedData}]`);
zf9nrax1

zf9nrax14#

我创建了一个包@jsonlines/core,它将jsonlines解析为对象流。
你可以试试下面的代码:

npm install @jsonlines/core
const fs = require("fs");
const { parse } = require("@jsonlines/core");

// create a duplex stream which parse input as lines of json
const parseStream = parse();

// read from the file and pipe into the parseStream
fs.createReadStream(yourLargeJsonLinesFilePath).pipe(parseStream);

// consume the parsed objects by listening to data event
parseStream.on("data", (value) => {
  console.log(value);
});

注意,parseStream是标准节点双工流。所以你也可以使用for await ... of或其他方式来使用它。

nimxete2

nimxete25#

当文件小到可以放入内存时,这里有另一个解决方案。它一次读取整个文件,通过在换行符处拆分(删除末尾的空行)将其转换为数组,然后解析每行。

import fs from "fs";

const parsed = fs
  .readFileSync(`data.jsonl`, `utf8`)
  .split(`\n`)
  .slice(0, -1)
  .map(JSON.parse)

相关问题