I have a data logger that records time, status & temperature by appending to a file. (The logger is called from a cron job.)
It would be great if I could read the data into a web page script as JSON, but I don't see a good way to do it -- either my logger is more complicated, or my reader is more complicated.
My data is lines like:
[ timestamp, "status", temperature ]
[ 123456789, "sync", 12345]
I can add commas to the line ends easily enough, but either way, it's not well-formatted JSON -- you need brackets around the whole thing.
So either my logger must detect an empty data file and add a leading bracket, plus seek to the end, back up a character, replace the last close-bracket with a comma, and then append its own record with an extra closing bracket, or the reader has to massage the pre-JSON by slicing off a trailing comma and adding brackets around.
Is there an easier way to do this?
CodePudding user response:
You can do this
I would use fetch
const str = `[ timestamp, "status", temperature ]
[ 123456789, "sync", 12345]`
const data = str.split(/\r?\n/) // line feed
.map(line => line
.replace(/[\[\]]/g,"") // remove square brackets (can be done in the regex below too
.match(/(".*?"|[^",\s] )(?=\s*,|\s*$)/g) // find stuff with or without quotes
.map(elem => isNaN(elem) ? elem : elem) // convert numbers back to numbers
);
console.log(data)
CodePudding user response:
The format you are using is similar one that is both established and excellent for logging: see JSON Lines and ndjson.
By slicing your input after the first line, you'll be left with JSON lines. Then you just need to iterate the lines and parse each line (optionally collecting into an array if desired).
Here's an example:
const LF = '\n';
function iterateJSONLines (jsonl, cb) {
for (const line of jsonl.trim().split(LF)) {
cb(JSON.parse(line));
}
}
/** handle the first (non-JSON) line in your input */
function separateHeaderFromJSONLines (input) {
for (let i = 0; i < input.length; i = 1) {
if (input[i] !== LF) continue;
return [input.slice(0, i).trim(), input.slice(i 1)];
}
}
function main (input) {
const [headerLine, jsonl] = separateHeaderFromJSONLines(input);
const arr = [];
iterateJSONLines(jsonl, arr.push.bind(arr));
console.log(headerLine);
console.log(arr);
}
const input = `[ timestamp, "status", temperature ]
[ 123456789, "sync", 12345]
[ 987654321, "anotherStatus", 54321]
`;
main(input);