0

I have two JSON files data.json and values.json. I want to read whatever the values of aws and bucket in values.json are, and use them in data.json. How can I achieve this with node js?

I have written a function that reads the content of the values.json file and stores them in a variable, but I am confused about how to write them to data.json as values of "aws": " " and "bucket": " ".

In cases where aws and bucket already have values, I want those existing values to be replaced by whatever was read from data.json. How can I implement this?

data.json

{
    "label": "storage record",
    "data": [
        {
            "id": "8902uw",
            "type": "config",
            "values": {
                "access": "$access",
                "key": "$key"
            }
        },
        {
            "id": "90yueps",
            "type": "upload",
            "input": "localhost: `$path`"
}
 {
            "id": "9028901",
            "type": "change",
            "name": "Adjust data",
            "action": ""
        }

            ]
        }

values.json

{
    "key": "7c4afc",
    "access": "784030"
    }

index.js

const fs = require("fs").promises;

async function jsonReader(filePath, values) {
  const data = await fs.readFile(filePath);
  try {
    return JSON.parse(data);
  } catch (err) {
    console.error(err);
  }
}



(async () => {
  const config = await jsonReader("./values.json");

  const path = values.path;
  const access = values.access;
  const key = values.key;
  const bucketPath = bucketPath;


  const data = await jsonReader("./data.json");

  const fixedData = data.data?.map((o) => {
    if (o.type == "upload") return { ...o,  path };
    if (o.type == "config") return { ...o,  acsess, key };
   if (o.type == "change") return { ...o,  bucketPath };
    
  });
  await fs.writeFile("./data.json", JSON.stringify({ data: fixedData}, null, 3 ));
})();

Tini
  • 169
  • 8

1 Answers1

1

First you need to change the current json and finally you need to write the modified json into you data.json again. I would recommend to you to use async/await instead of use promise then directly. I rewrite your code with async/await structure, but you can adapt if you prefer to use callback instead. Follow the example code:

const fs = require("fs").promises;

async function jsonReader(filePath, values) {
  const data = await fs.readFile(filePath);
  try {
    return JSON.parse(data);
  } catch (err) {
    console.log(err);
  }
}

(async () => {
  const credentials = await jsonReader("./values.json");
  const aws = credentials.aws;
  const bucket = credentials.bucket;
  const data = await jsonReader("./data.json");

  const fixedData = data.data?.map((o) => {
    if (o.type == "storage") return { ...o, aws, bucket };
  });
  await fs.writeFile("./data.json", JSON.stringify({ data: fixedData }));
})();

Edit: I put with .map instead of .foreach to avoid mutable the array as mentioned by @JSmart523

Julien Ambrosio
  • 311
  • 2
  • 6
  • in if condition you can use this also if(d.hasOwnProperty('aws')){ d.aws = d.aws } – Gopal Dec 11 '22 at 03:11
  • 3
    If you don't want to mutate and instead want to create new values, then instead of `data.data.forEach()` you could do `const fixedData = {...data, data: data.data?.map(o => {...o, ...aws})};`. However, I don't want to write that in a separate answer because I like Julien's a lot and don't think it's fair to compete with it. – JSmart523 Dec 11 '22 at 03:11
  • @JSmart523 your suggestion is good because we must prefer to code as immutable to avoid side effects and etc. I will update my answer, mentioning you =D – Julien Ambrosio Dec 11 '22 at 03:45
  • 1
    @Tini test again with the new sample code, I added some edit in the code, now I returning directly the parsed data. It's makes more sense – Julien Ambrosio Dec 11 '22 at 19:57
  • `const credentials` is `undefined.`, so the whole code returns `TypeError: Cannot read properties of undefined (reading 'aws')` – Tini Dec 11 '22 at 19:57
  • @JulienAmbrosio When I ran it the first time, it changes the `data.json` file to include the new values. But everything appears on the same line. When I rerun the code, I get this new error: `TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined` – Tini Dec 11 '22 at 20:21
  • @JulienAmbrosio I tried this `await fs.writeFile("./data.json", (JSON.parse(JSON.stringify(fixedData))));` but didn't work – Tini Dec 11 '22 at 20:26
  • 1
    Try to debug what is returning after you read the data.json at the line of: ` return JSON.parse(data);` however I will test the code with your jsons locally. I created this example without running. – Julien Ambrosio Dec 11 '22 at 20:27
  • 1
    First you need to understand what's JSON.parse and what's JSON.stringify. One of them transform the string to json object and the second transform a json object as string. One second, I will debug for you – Julien Ambrosio Dec 11 '22 at 20:29
  • 1
    The problem is simple @Tini. I changed the JSON result, so basically the object data inside the json doesn't exist after the save anymore. So, because of that, only works in the first time. To fix, in write method, call it `JSON.stringify({ data: fixedData })`, now it will run like you want. I will update the answer to put the correct code. – Julien Ambrosio Dec 11 '22 at 20:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/250331/discussion-between-tini-and-julien-ambrosio). – Tini Dec 11 '22 at 23:44
  • @JulienAmbrosio Thank you, I have checked out the difference between `JSON.parse` and `JSON.stringify.` I am trying to use the current implementation on differently structured data, but I am getting ` TypeError: Cannot read properties of undefined (reading 'data')` while mapping. I have updated my code to show what I tried. – Tini Dec 12 '22 at 00:34