1

I am making exernal api calls which return json objects. After all calls are made I want to write the collection of json objects to file. However when I do this it is writing to file in the wrong format.

EDIT: the findPrices() function is being called inside a loop.

priceSearch1Array = [];

function findPrices(res) {

  (api.get({
    origin: A,
    destination: B,
  }).then(function(response) {

    priceSearchVar = JSON.stringify(response.result.data);
    priceSearch1Array.push(priceSearchVar);

  }).catch(function(error) {
    console.log('error and continue' + error);
  }))

}

After all API calls, the array is sent to file.

fs.writeFileSync('api/data/destinations3.json', priceSearch1Array);

The current output is example :

[{flight:"data", segments: { price:"23.22"}}],
[{flight:"data", segments: { price:"78.45"}}],
[{flight:"data", segments: { price:"48.45"}}]

When i need it to write to file in the format :

[ {flight:"data", segments: { price:"23.22"}},
  {flight:"data", segments: { price:"78.45"}},
  {flight:"data", segments: { price:"48.45"}} ]

I need the json objects in a list format and then add to file rather than an array per object. Is there a way to do this?

2
  • 1
    Any chance response.result.data is actually a single-item array, and not just the item itself? Commented Apr 4, 2019 at 14:07
  • Before I was writing the response.result.data as priceSearchVar to file from the loop and it was in the correct format as just the json object, However now that i need to keep the server running and writing to file would trigger a server restart, i need to write to file once I have collected all the responses, resulting in having to rearrange how I write to file Commented Apr 4, 2019 at 14:11

3 Answers 3

1
    function findPrices(res) {

      (api.get({
        origin: A,
        destination: B,
      }).then(function(response) {
        let data = []

        try {
          // read the data and convert into json
          data = fs.readFileSync('api/data/destinations3.json', 'utf8')
          data = JSON.parse(data)
          data = Array.isArray(data) ? data : [data]
        } catch(err) {}

        const responseData = response.result.data
        const priceSearch1Array = JSON.stringify([ ...data, responseData ])

        fs.writeFileSync('api/data/destinations3.json', priceSearch1Array);

      }).catch(function(error) {
        console.log('error and continue' + error);
      }))

    }
Sign up to request clarification or add additional context in comments.

Comments

0

I think that perhaps the structure of the code is what's making this slightly confusing to debug. I've reformatted things for this example but it's not essential to solve the problem that you're experiencing.

There are two problems that I think may be causing the issues with this.

Firstly, we're getting an array of arrays of objects, when we actually want an array of objects. This is easy enough to solve if you flatten the array as shown in the function below.

Secondly, we're writing the raw object to file. As I understand it, and from some testing I've done, fs is going to write the data you pass it to file as a string. That means that it'll use a fairly simplistic conversion, and your objects will come out as [Object object] as you saw. To get around this, we can use JSON.stringify to get a more appropriate conversion. I've simulated the fs and api calls, but the example gives you a rough idea.

I've also converted this to use map and Promise.all instead of pushing to an array from a loop. I feel it's a little easier to understand this way, if it doesn't make sense, please feel free to comment and I'll go into more detail.

const api = {
  get: data => new Promise(res => {
    setTimeout(() => res([data]), 1000)
  })
}

const fs = {
  writeFileSync: (location, data) => {
    console.log(
      `writing data ${data} to ${location}`
    );
    console.log('=====================');
  }
}

const data = [
  {A: 'test', B: 'another test'},
  {A: 'test2', B: 'another test2'},
];

const makeApiCallFromDataItem = dataItem => api.get({
  origin: dataItem.A,
  destination: dataItem.B,
});

const callApiForAllDataItems = data => Promise
  .all(data.map(makeApiCallFromDataItem))

const flatten = dataIn => dataIn.reduce((prev, curr) => [
  ...prev,
  ...curr
])

callApiForAllDataItems(data)
  .then(data => {
    fs.writeFileSync('api/data/destinations3.json', data)
  })
  
callApiForAllDataItems(data)
  .then(data => {
    fs.writeFileSync('api/data/destinations3.json', JSON.stringify(data))
  })
  
callApiForAllDataItems(data)
  .then(data => {
    const flatData = flatten(data);
    fs.writeFileSync('api/data/destinations3.json', JSON.stringify(flatData))
  })

1 Comment

Fabulous ! thanks very much, I will give this a go!
0

Try replacing priceSearchVar = JSON.stringify(response.result.data); with just priceSearchVar =response.result.data and replace priceSearch1Array.push(priceSearchVar) with priceSearch1Array.push(JSON.stringify(...priceSearchVar))

or maybe it can be done in just one line, priceSearch1Array.push(JSON.stringify(...response.result.data))

2 Comments

Thanks for your help! So I tried this and it solved the problem for multiple arrays, but now it is printing {flight:"data", segments: { price:"23.22"}}, {flight:"data", segments: { price:"78.45"}}, {flight:"data", segments: { price:"48.45"}} without an overall array brackets. I tried pushing that to an array but it printed as [Object object],[Object object] etc , I wasn't pushing priceSearch1Array to NewArray inside a loop, so i am unsure of why each object was added to own array?
ahh sorry, it may be because of priceSearchVar = JSON.stringify(response.result.data);. maybe try to replace that line with just priceSearchVar = response.result.data. I had to use ...priceSearchVar to spread the properties before stringifying priceSearchVar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.