Как добавить несколько объектов Json в один массив из цикла - PullRequest
1 голос
/ 04 апреля 2019

Я делаю внешние вызовы API, которые возвращают объекты JSON. После всех вызовов я хочу записать коллекцию объектов json в файл. Однако, когда я делаю это, он записывает в файл в неправильном формате.

EDIT: функция findPrices () вызывается внутри цикла.

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);
  }))

}

После всех вызовов API массив отправляется в файл.

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

Пример токового выхода:

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

Когда мне нужно записать в файл в формате:

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

Мне нужны объекты json в виде списка, а затем добавить в файл, а не в массив для каждого объекта. Есть ли способ сделать это?

Ответы [ 3 ]

1 голос
/ 04 апреля 2019
    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);
      }))

    }
0 голосов
/ 04 апреля 2019

Я думаю, что, возможно, структура кода - то, что делает это немного запутанным для отладки. Я переформатировал вещи для этого примера, но не обязательно решать проблему, с которой вы столкнулись.

Есть две проблемы, которые, я думаю, могут быть причиной проблем с этим.

Во-первых, мы получаем массив массивов объектов, когда нам на самом деле нужен массив объектов. Это достаточно легко решить, если вы сгладить массив, как показано в функции ниже.

Во-вторых, мы записываем необработанный объект в файл. Насколько я понимаю, и после некоторого тестирования, которое я провел, fs запишет данные, которые вы передаете, в файл в виде строки. Это означает, что он будет использовать довольно упрощенное преобразование, и ваши объекты будут выглядеть как [Object object], как вы видели. Чтобы обойти это, мы можем использовать JSON.stringify, чтобы получить более подходящее преобразование. Я смоделировал вызовы fs и api, но пример дает вам приблизительное представление.

Я также преобразовал это, чтобы использовать map и Promise.all вместо передачи в массив из цикла. Я чувствую, что это немного легче понять таким образом, если это не имеет смысла, пожалуйста, не стесняйтесь комментировать, и я углублюсь в подробности.

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))
  })
0 голосов
/ 04 апреля 2019

Попробуйте заменить priceSearchVar = JSON.stringify(response.result.data); просто priceSearchVar =response.result.data и заменить priceSearch1Array.push(priceSearchVar) на priceSearch1Array.push(JSON.stringify(...priceSearchVar))

или, может быть, это можно сделать в одну строку, priceSearch1Array.push(JSON.stringify(...response.result.data))

...