Объединение 2 объектов JSON, когда один еще не существует

#javascript #node.js

#javascript #node.js

Вопрос:

 function fetchAPI(string) {
    return fetch(string).then(function(response) {
        return response.json();
    }).then(function(json) {
        return json;
    });
}

try {
   fetchAPI(`https://api.hypixel.net/skyblock/auctions?key=${apikey}`).then(
       function(result1) {
          delete result1.success;
          delete result1.page;
          delete result1.totalAuctions;
          delete result1.lastUpdated;
          var pages = result1.totalPages;
          delete result1.totalPages;
          // eslint-disable-next-line no-shadow
          for (var page = 0; page < pages; page  ) {
             fetchAPI(`https://api.hypixel.net/skyblock/auctions?key=${apikey}amp;page=${page}`).then(function(results) {
                  delete results.success;
                  delete results.page;
                  delete results.totalAuctions;
                  delete results.lastUpdated;
                  delete results.totalPages;
                  var i = 0;
                  for (i = 0; i < results.auctions.length; i  ) {
                      // eslint-disable-next-line quotes
                      if (results.auctions[i].item_name != "Enchanted Book") {
                        delete results.auctions[i];
                      }
                  }
                  fs.appendFile('finalresult.json', JSON.stringify(results), err => {
                    if (err) console.log(err);
                  });
                      
             });
          }
       },
   });
} 
catch (error) {
    console.log(error);
}
  

В коде я получаю информацию из API (функция fetchAPI), которая возвращает ответ JSON. Чтобы получить всю информацию из API, мне нужно запросить каждую страницу конкретной конечной точки, отсюда for (var page = 0; page < pages; page ) и цикл. Затем мне нужно отфильтровать JSON:

 for (i = 0; i < results.auctions.length; i  ) {
    // eslint-disable-next-line quotes
    if (results.auctions[i].item_name != "Enchanted Book") {
       delete results.auctions[i];
    }
}
  

Затем, наконец, мне нужно сохранить всю информацию JSON с каждой страницы в один файл. Единственная проблема заключается в том, что в будущем мне нужно будет читать из этого файла, и когда я это делаю fs.appendFile('finalresult.json', JSON.stringify(results)); , он не сохраняет формат JSON. Есть ли способ, которым я могу создать один длинный файл JSON, состоящий из данных API?

Пример данных JSON («аукционы» будут содержать 1000 элементов на странице, но будут отфильтрованы, поэтому среднее значение снизится до 300 на страницу, поэтому я просто включу пример элемента):

 {
  "success": true,
  "page": 0, // The current page
  "totalPages": 32, // Total amount of pages avaliable
  "totalAuctions": 31267, // Total amount of results in the auction house
  "lastUpdated": 1571065561345, // Unix timestamp in milliseconds of when the data last updated in the API
  "auctions": [ // The auctions themselves
    {
      "uuid": "bc581ce675e94a0c88ac9deae06090f0",
      "auctioneer": "96a7c06732f54c1382ab6a2515dbb960",
      "profile_id": "96a7c06732f54c1382ab6a2515dbb960",
      "coop": [
        "96a7c06732f54c1382ab6a2515dbb960"
      ],
      "start": 1571049581232,
      "end": 1571071181232,
      "item_name": "Magical Mushroom Soup",
      "item_lore": "§7Consuming this Magical Mushroomn§7Soup on your private islandn§7allows the player to fly for §a2n§aminutes§7. Leaving the privaten§7island will remove the effect!nn§a§lUNCOMMON",
      "extra": "Magical Mushroom Soup Mushroom Soup",
      "category": "consumables",
      "tier": "UNCOMMON",
      "starting_bid": 256,
      "item_bytes": "...",
      "claimed": false,
      "claimed_bidders": [],
      "highest_bid_amount": 256,
      "bids": [
        {
          "auction_id": "bc581ce675e94a0c88ac9deae06090f0",
          "bidder": "70aafcc6764b45ff80e60226193a0784",
          "profile_id": "70aafcc6764b45ff80e60226193a0784",
          "amount": 256,
          "timestamp": 1571065921089
        }
      ]
    }
  ]
}
  

Все, кроме «аукционов», удаляется из JSON к тому времени, когда мне нужно его объединить

Комментарии:

1. JSON внутри кода — это просто объект and . Конечно, вы можете добавить туда поля. Но вы должны вызывать только stringify один раз в конце. Поэтому, пожалуйста, покажите нам примеры JSON, которые вы пытаетесь объединить.

2. Будет сделано, дайте мне секунду, пока я получу это и обновлю сообщение.

3. @Anton Я добавил пример JSON. По сути, оба JSON имеют одинаковый формат, и я написал некоторый код, чтобы удалить все, кроме «аукционов». В остальном JSON-файлы почти одинаковые.

Ответ №1:

Извини, чувак. Я сегодня устал и забыл об асинхронной природе вашего кода.

Вот полностью рабочий пример (даже без apiKey). Вы можете запустить его:

 //const originalUrl = `https://api.hypixel.net/skyblock/auctions?key=${apikey}`;
const originalUrl = `https://api.hypixel.net/skyblock/auctions?rnd=1`;
const nameToSearch = 'Enchanted Book';

function showLoaded(count, total) {
  const el = document.getElementById('loader');
  if (count) el.innerText = ''   count   ' of '   total;
  else el.innerText = 'ALL';
}

function fetchAPI(string) {
  return fetch(string)
   .then(response => response.json());
}

function getAuctionsFromPage(page, totalPages) {
  return fetchAPI(originalUrl   `amp;page=${page}`)
    .then(result => {
      loaded  ;
      showLoaded(loaded, totalPages);
      return result.auctions
    })
    .then(auctions => auctions.filter(auction => auction.item_name == nameToSearch));
}

let loaded = 0;

function collectData(totalPages) {
  const allPages = [];
  loaded = 0;
  for (let i = 0; i < totalPages; i  ) {
    allPages.push(getAuctionsFromPage(i, totalPages));
  }
  return Promise.all(allPages)
    .then(auctions => auctions.flat(1))
    .then(auctions => {
      showLoaded();
      return {
        auctions
      }
    });
}

function saveToFile(data) {
  // Put data to file
  fs.appendFile('finalresult.json', JSON.stringify(data), err => {
    if (err) console.log(err);
  });
}

function saveToConsole(data) {
  const jsonData = JSON.stringify(data);
  //console.log(jsonData);
  document.getElementById('console').innerHTML = 'We found '   data.auctions.length   ' items named '   nameToSearch   '<br/>Data size is '   jsonData.length   ' bytes';
}

try {
  document.getElementById('loader').innerText = 'Getting total pages...';
  fetchAPI(originalUrl)
    .then(result => result.totalPages)
    .then(totalPages => collectData(totalPages))
    .then(data => saveToConsole(data));
} catch (error) {
  console.log(error);
}  
 <div>Loaded: <span id="loader">0</span></div>
<div id="console"></div>  

Примечание: чтобы сохранить данные в файл, вам необходимо изменить .then(data => saveToConsole(data)) на .then(data => saveToFile(data))

Комментарии:

1. Хорошо, спасибо вам за это. Я полагаю, что мне удалось перевести это на node.js (который был отмечен в вопросе, но ничего страшного, если вы пропустили его из-за усталости.) Единственное, о чем я получал ошибки (потому что я использую node.js , а не javascript браузера) был const el = jsdom.document.getElementById('loader'); в функции showLoaded. Ошибка TypeError: Cannot read property 'getElementById' of undefined была передана на консоль, что, как я предполагаю, связано с тем, что она выполняется в node.js . Какие решения вы можете дать для этого? Кстати, спасибо за всю вашу помощь!

2. @DeltaCodes да ладно =) вам не нужен ни один из getElementById (не работает в node). Я добавил их только для тестирования. Таким образом, вы можете удалить: showLoaded function, saveToConsole function, эти две строки: loaded ; showLoaded(loaded, totalPages); , эту строку: let loaded = 0; , это loaded = 0; и это: showLoaded(); и, наконец, это: document.getElementById('loader').innerText = 'Getting total pages...';

3. Вы СПАСЛИ ЖИЗНЬ! Большое вам спасибо!