Як оновити значення у файлі json та зберегти його через node.js


84

Як оновити значення у файлі json та зберегти його через node.js? У мене є вміст файлу:

var file_content = fs.readFileSync(filename);
var content = JSON.parse(file_content);
var val1 = content.val1;

Тепер я хочу змінити значення val1та зберегти його у файл.

Відповіді:


127

Зробити це асинхронно досить просто. Це особливо корисно, якщо ви стурбовані блокуванням потоку (ймовірно).

const fs = require('fs');
const fileName = './file.json';
const file = require(fileName);
    
file.key = "new value";
    
fs.writeFile(fileName, JSON.stringify(file), function writeJSON(err) {
  if (err) return console.log(err);
  console.log(JSON.stringify(file));
  console.log('writing to ' + fileName);
});

Застереження полягає в тому, що json записується до файлу в один рядок і не обробляється. напр .:

{
  "key": "value"
}

буде...

{"key": "value"}

Щоб цього уникнути, просто додайте ці два додаткові аргументи JSON.stringify

JSON.stringify(file, null, 2)

null- представляє функцію заміни. (у цьому випадку ми не хочемо змінювати процес)

2 - представляє пробіли для відступу.


50
//change the value in the in-memory object
content.val1 = 42;
//Serialize as JSON and Write it to a file
fs.writeFileSync(filename, JSON.stringify(content));

6
Загалом, було б краще використовувати асинхронний запис, оскільки це основний фокус Node. Звичайно, без бачення оточуючого коду було б важко дати остаточну відповідь. Навряд чи вам дійсно знадобиться синхронізація, якщо вам не потрібно бути абсолютно впевненим, що нічого іншого не може статися, поки запис не завершиться. До того ж, звичайно, це повинно мати перевірку помилок, оскільки ви НІКОЛИ не можете бути впевнені, що запис файлу буде успішним.
Джуліан Найт,

4
асинхронізація проти синхронізації залежить точно від того, що ви робите в якому контексті. Якщо це в мережі, вам потрібна асинхронізація. Для утиліти командного рядка синхронізація є відповідною парадигмою в більшості простих випадків, але просто поштовхом до коліна сказати «асинхронізація краще» є неправильним. Мій фрагмент базується на фрагменті OP для контексту. Питання також не в обробці помилок, і якщо запис файлу не вдається, вихід із трасуванням стека є розумною поведінкою за замовчуванням, оскільки ви не можете багато чого зробити, щоб відновити після цього.
Пітер Лайонс

Оскільки вузол заснований на циклі, асинхронізація майже завжди краща, щоб ви не блокували цикл, це взагалі не реакція ритму, просто стандартна практика для розробника вузлів. Я вже говорив, що це залежить від вимоги, і я не думаю, що Q щось говорить про командний рядок? Крім того, загалом, якщо це частина більшого набору коду (не роз'ясненого в OP), то обробка помилок завжди є розумною та найкращою практикою. Викидати трасування стека - це нормально для розробників, але для всіх інших - лайно.
Джуліан Найт,

22
async - це паралельна техніка. Якщо вам потрібна паралельність, для правильної роботи вузла потрібна асинхронізація (не "краща"). Якщо у вас немає одночасності, вам не потрібна асинхронізація. Справа в тому, що вам потрібно насправді зрозуміти, що асинхронізація робить для вас і чому. Це по суті не "краще" без причини, і вам не потрібно запам'ятовувати це як "найкращу практику". Якщо операційна програма пише утиліту командного рядка для зміни файлу JSON, тоді вихід, async ускладнює код без причини, оскільки паралельність не потрібна.
Пітер Лайонс

Я будую інструмент командного рядка вузла. Якщо синхронізація не записана, файл може бути заблокований, коли висновок мого інструменту буде прив’язаний до наступного інструменту. Є дуже вагомі причини використовувати синхронізацію. І вагомі причини використовувати async.
TamusJRoyce,

3

на додаток до попередньої відповіді додайте каталог шляху до файлу для операції запису

 fs.writeFile(path.join(__dirname,jsonPath), JSON.stringify(newFileData), function (err) {}

2
// read file and make object
let content = JSON.parse(fs.readFileSync('file.json', 'utf8'));
// edit or add property
content.expiry_date = 999999999999;
//write file
fs.writeFileSync('file.json', JSON.stringify(content));

0

Для тих, хто хоче додати елемент до колекції json

function save(item, path = './collection.json'){
    if (!fs.existsSync(path)) {
        fs.writeFile(path, JSON.stringify([item]));
    } else {
        var data = fs.readFileSync(path, 'utf8');  
        var list = (data.length) ? JSON.parse(data): [];
        if (list instanceof Array) list.push(item)
        else list = [item]  
        fs.writeFileSync(path, JSON.stringify(list));
    }
}

0

Я настійно рекомендую не використовувати синхронні (блокуючі) функції, оскільки вони виконують інші паралельні операції . Замість цього використовуйте асинхронні fs.promises :

const fs = require('fs').promises

const setValue = (fn, value) => 
  fs.readFile(fn)
    .then(body => JSON.parse(body))
    .then(json => {
      // manipulate your data here
      json.value = value
      return json
    })
    .then(json => JSON.stringify(json))
    .then(body => fs.writeFile(fn, body))
    .catch(error => console.warn(error))

Пам'ятайте, що setValueповертає очікуване обіцянку, вам потрібно буде використовувати функцію .then або, в рамках функцій асинхронізації, оператор await .

// await operator
await setValue('temp.json', 1)           // save "value": 1
await setValue('temp.json', 2)           // then "value": 2
await setValue('temp.json', 3)           // then "value": 3

// then-sequence
setValue('temp.json', 1)                 // save "value": 1
  .then(() => setValue('temp.json', 2))  // then save "value": 2
  .then(() => setValue('temp.json', 3))  // then save "value": 3

0

Зберігайте дані після завершення завдання

fs.readFile("./sample.json", 'utf8', function readFileCallback(err, data) {
        if (err) {
          console.log(err);
        } else {
          fs.writeFile("./sample.json", JSON.stringify(result), 'utf8', err => {
            if (err) throw err;
            console.log('File has been saved!');
          });
        }
      });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.