source

JSON.stringify가 RangeError를 슬로우합니다.거대한 개체의 문자열 길이가 잘못되었습니다.

gigabyte 2023. 3. 20. 23:17
반응형

JSON.stringify가 RangeError를 슬로우합니다.거대한 개체의 문자열 길이가 잘못되었습니다.

제목에서 알 수 있듯이, 나는 내 Node.js 앱에서 거대한 JavaScript 객체를 문자열화하려고 한다.개체는 다시 거대하고(메가바이트의 수 십 개), 함수는 포함되어 있지 않습니다.직렬화된 개체를 파일에 써야 합니다.지금 내가 얻는 것은 다음과 같다.

RangeError: Invalid string length
  at Object.stringify (native)
  at stringifyResult (/my/file.js:123:45) -> line where I use JSON.stringify

그 문제를 어떻게 해결할지 아세요?

저도 이 unhelpful/오해의 nodejs 오류 메시지를 보고 nodejs github에서 문제를 예약했습니다.

범위 오류:잘못된 문자열 길이 --- 메모리 부족이라고 표시되어야 합니다.

@sandeepanu에서 언급했듯이, @madhunimmo의 훌륭한 작은 솔루션이 있습니다.한 번에 하나의 요소만 문자열화하면 됩니다.

let out = "[" + yourArray.map(el => JSON.stringify(el)).join(",") + "]";

오브젝트를 매우 많은 키/속성으로 문자열화하려는 경우Object.entries()먼저 키/값 쌍의 배열로 변환합니다.

let out = "[" + Object.entries(yourObject).map(el => JSON.stringify(el)).join(",") + "]";

그래도 문제가 해결되지 않으면 스트리밍 방식을 사용하는 것이 좋습니다.단, 어레이를 분할하여 여러 개로 저장할 수도 있습니다.jsonl(한 줄에 1개의 객체) 파일:

// 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();

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");
    }
);

여기서 샘플 코드를 가져왔어요

다음은 작업을 수행할 수 있는 간단한 도우미 파일입니다.

const fs = require('fs');
const json = require('big-json');
 
// pojo will be sent out in JSON chunks written to the specified file name in the root 
function makeFile(filename, pojo){

    const stringifyStream = json.createStringifyStream({
        body: pojo
    });

    stringifyStream.on('data', function(strChunk) {
        fs.appendFile(filename, strChunk, function (err) {
            if (err) throw err;
        })
    });

}

module.exports = {
    makeFile
}

언급URL : https://stackoverflow.com/questions/29175877/json-stringify-throws-rangeerror-invalid-string-length-for-huge-objects

반응형