JSON.stringify 抛出 RangeError: Invalid string length for large objects
Posted
技术标签:
【中文标题】JSON.stringify 抛出 RangeError: Invalid string length for large objects【英文标题】:JSON.stringify throws RangeError: Invalid string length for huge objects 【发布时间】:2015-05-24 09:56:21 【问题描述】:正如标题所暗示的,我正在尝试在我的 Node.js 应用程序中使用 JSON.stringify
对巨大的 javascript 对象进行字符串化。这些对象 - 再次 - 巨大(数十兆字节),它们不包含任何功能。我需要将序列化的对象写入文件。我现在得到的是这样的:
RangeError: Invalid string length
at Object.stringify (native)
at stringifyResult (/my/file.js:123:45) -> line where I use JSON.stringify
知道如何解决这个问题吗?
【问题讨论】:
这可能只是宇宙在暗示你以不同的方式解决问题。 也就是说,如果您正在为输出准备数据结构,您可以编写自己的 JSON 序列化程序,以增量方式写入输出流,而不是创建单个大字符串。这不会超级简单,但也不会超级难。 我认为有流式传输或缓冲的 JSON 反序列化器。 寻找类似的答案,除了 javascript 客户端(无节点)。同时,这是您的问题的答案,@boris:***.com/questions/24153996/… 【参考方案1】:我发现 JSONStream 是原生 JSON.stringify 的可靠替代方案,它适用于大型对象。例如:
var fileSystem = require( "fs" );
var JSONStream = require( "JSONStream" );
var records = [
id: 1, name: "Terminator" ,
id: 2, name: "Predator" ,
id: 3, name: "True Lies" ,
id: 4, name: "Running Man" ,
id: 5, name: "Twins"
// .... hundreds of thousands of records ....
];
var transformStream = JSONStream.stringify();
var outputStream = fileSystem.createWriteStream( __dirname + "/data.json" );
transformStream.pipe( outputStream );
records.forEach( transformStream.write );
transformStream.end();
outputStream.on(
"finish",
function handleFinish()
console.log("Done");
);
从here获取示例代码。
【讨论】:
【参考方案2】:正如@sandeepanu 所提到的,there's a great little solution by @madhunimmo 如果您想对一个巨大的数组进行字符串化。一次只对一个元素进行字符串化:
let out = "[" + yourArray.map(el => JSON.stringify(el)).join(",") + "]";
如果您尝试对具有大量键/属性的对象进行字符串化,那么您可以先在其上使用Object.entries()
将其转换为键/值对数组:
let out = "[" + Object.entries(yourObject).map(el => JSON.stringify(el)).join(",") + "]";
如果这仍然不起作用,那么您可能希望使用流式处理方法,尽管您可以将数组分割成多个部分并存储为多个 jsonl
(每行一个对象)文件:
// untested code
let numFiles = 4;
for(let i = 0; i < numFiles; i++)
let out = arr.slice((i/numFiles)*arr.length, ((i+1)/numFiles)*arr.length).map(el => JSON.stringify(el)).join(",");
// add your code to store/save `out` here
一种流式传输方法(新的,目前仅在 Chrome 中支持,但可能会出现在其他浏览器,甚至是某种形式的 Deno 和 Node.js)是使用File System Access API。代码看起来像这样:
// untested code
const dirHandle = await window.showDirectoryPicker();
const fileHandle = await dirHandle.getFileHandle('yourData.jsonl', create: true );
const writable = await fileHandle.createWritable();
for(let el of yourArray)
await writable.write(JSON.stringify(el)+"\n");
await writable.close();
【讨论】:
【参考方案3】:我也看到了这个无用/误导性的 nodejs 错误消息,所以我在 nodejs github 上预订了一个问题
RangeError: Invalid string length --- it should be saying Out Of Memory
【讨论】:
另请查看:dev.to/madhunimmo/…以上是关于JSON.stringify 抛出 RangeError: Invalid string length for large objects的主要内容,如果未能解决你的问题,请参考以下文章