Parse JSON Lines Records Incrementally
An incremental JSON Lines reader that yields parsed records line by line with strict validation and clear errors for malformed input.
Code
export async function* parseJsonLines(source, validate) {
let buffer = "";
let lineNo = 0;
for await (const chunk of source) {
buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
let nl;
while ((nl = buffer.indexOf("\n")) !== -1) {
const raw = buffer.slice(0, nl).replace(/\r$/, "");
buffer = buffer.slice(nl + 1);
lineNo += 1;
if (raw.trim() === "") continue;
let record;
try {
record = JSON.parse(raw);
} catch (err) {
throw new Error(`invalid JSON on line ${lineNo}: ${err.message}`);
}
if (validate) {
const problem = validate(record);
if (problem) throw new Error(`record failed validation on line ${lineNo}: ${problem}`);
}
yield { line: lineNo, record };
}
}
if (buffer.trim() !== "") {
lineNo += 1;
let record;
try {
record = JSON.parse(buffer);
} catch (err) {
throw new Error(`invalid JSON on line ${lineNo}: ${err.message}`);
}
if (validate) {
const problem = validate(record);
if (problem) throw new Error(`record failed validation on line ${lineNo}: ${problem}`);
}
yield { line: lineNo, record };
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.