0

Although following the excellent information in https://stackoverflow.com/a/47116829/11308019 — especially the "Year 2018 answer" — I am trying to figure out a JSON.stringify problem. Example code follows...

const globAll = require('glob-all')
const fs = require('fs')
const cacheFile = '.base64imgs.json'

// clear cacheFile...
fs.writeFileSync(cacheFile,'')
let bCache = {}

files = globAll.sync([
  'src/images/*.jpg',
  'src/images/*.png',
])

files.forEach(file => {
  var bRes = `data for ${file} would go here`
  var bAdd = {file, bRes}
  bCache =  {...bCache, ...bAdd}
  fs.writeFileSync(cacheFile, JSON.stringify(bCache, null, 2), {flag: 'a'})
})

This results in output in .base64imgs.json like the following:

{
  "file": "src/images/1984-07-11_01_retouched_1280x720.jpg",
  "bRes": "data for src/images/1984-07-11_01_retouched_1280x720.jpg would go here"
}{
  "file": "src/images/2020-01-31--curmudgeonishish-2019_1280x726.jpg",
  "bRes": "data for src/images/2020-01-31--curmudgeonishish-2019_1280x726.jpg would go here"
}{
  "file": "src/images/alarm-clock-4711181_1280x853.jpg",
  "bRes": "data for src/images/alarm-clock-4711181_1280x853.jpg would go here"
}{
  "file": "src/images/almond-21502_1280x853.jpg",
  "bRes": "data for src/images/almond-21502_1280x853.jpg would go here"
}

...which obviously isn't valid JSON because there's no comma between the objects within the containing bCache object. (I also tried using arrays only, arrays within an object, objects within an array, etc.; same results each time.) I assume the fault is my own, but my days-long searches for answers in SO and other similar sources haven't shown me what I'm doing wrongly. So, any help and/or correction will be greatly appreciated!

Bryce Wray
  • 285
  • 3
  • 12
  • 3
    Shouldn't `bCache` be an array rather than an object? so `let bCache = [];` and `bCache = [...bCache, bAdd];`. – Heretic Monkey Jun 05 '20 at 20:49
  • @HereticMonkey did try all combos as noted in last paragraph. No joy. :-/ – Bryce Wray Jun 05 '20 at 20:51
  • 1
    Besides the array instead of object, part of your problem is using `...bAdd` instead of just `bAdd` — Heretic Monkey shows it but doesn't mention it... you want to add the _object_, but with `...bAdd` you are first _expanding_ bAdd with the spread operator and adding _the expansion_ to bCache. – Stephen P Jun 05 '20 at 21:04
  • @HereticMonkey --- from what the others said below, looks as if I should've listened to you in the first place. Thanks. – Bryce Wray Jun 05 '20 at 21:04

2 Answers2

2

You'll want to use an array instead of an object for bCache. And you should probably write out all at once instead of appending in a loop.

let bCache = []
let files = ['file 1','file 2','file 3']

files.forEach(file => {
  var bRes = `data for ${file} would go here`
  var bAdd = {file, bRes}
  bCache = [...bCache, bAdd]
})
console.log(JSON.stringify(bCache, null, 2))
JstnPwll
  • 8,585
  • 2
  • 33
  • 56
1

Don't write the JSON inside the loop. Create an array of all the data, and write it once at the end of the loop.

const globAll = require('glob-all')
const fs = require('fs')
const cacheFile = '.base64imgs.json'

files = globAll.sync([
  'src/images/*.jpg',
  'src/images/*.png',
])

bCache = files.map(file => {
  var bRes = `data for ${file} would go here`
  return {file, bRes}
});

fs.writeFileSync(cacheFile, JSON.stringify(bCache, null, 2));
Barmar
  • 741,623
  • 53
  • 500
  • 612