Jak zaktualizować wartość w pliku JSON i zapisać ją za pośrednictwem node.js.


85

Jak zaktualizować wartość w pliku json i zapisać ją za pośrednictwem node.js? Mam zawartość pliku:

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

Teraz chcę zmienić wartość val1i zapisać ją w pliku.

Odpowiedzi:


131

Robienie tego asynchronicznie jest dość łatwe. Jest to szczególnie przydatne, jeśli obawiasz się blokowania wątku (prawdopodobnie).

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

Jedynym zastrzeżeniem jest to, że json jest zapisywany do pliku w jednej linii i nie jest upiększany. dawny:

{
  "key": "value"
}

będzie...

{"key": "value"}

Aby tego uniknąć, po prostu dodaj te dwa dodatkowe argumenty do JSON.stringify

JSON.stringify(file, null, 2)

null- reprezentuje funkcję zamiennika. (w tym przypadku nie chcemy zmieniać procesu)

2 - reprezentuje spacje do wcięcia.


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
Ogólnie rzecz biorąc, lepiej byłoby użyć zapisu asynchronicznego, ponieważ jest to główny cel Node. Oczywiście bez zapoznania się z otaczającym kodem trudno byłoby udzielić ostatecznej odpowiedzi. Jest mało prawdopodobne, że naprawdę będziesz potrzebować synchronizacji, chyba że musisz mieć absolutną pewność, że nic innego się nie stanie, dopóki zapis nie zostanie zakończony. Dodatkowo, oczywiście, powinno to mieć moduł sprawdzania błędów, ponieważ NIGDY nie możesz być pewien, że zapis pliku się powiedzie.
Julian Knight

4
async vs. sync zależy dokładnie od tego, co robisz w jakim kontekście. Jeśli jest to usługa sieciowa, potrzebujesz asynchronizacji. W przypadku narzędzia wiersza poleceń synchronizacja jest odpowiednim paradygmatem w większości prostych przypadków, ale samo odruchowe stwierdzenie „asynchronizacja jest lepsza” nie jest poprawne. Mój fragment jest oparty na fragmencie OP dla kontekstu. Pytanie nie dotyczy również obsługi błędów, a jeśli zapis pliku się nie powiedzie, wyjście ze śladem stosu jest rozsądnym domyślnym zachowaniem, ponieważ niewiele można zrobić, aby to naprawić.
Peter Lyons

Ponieważ węzeł jest oparty na pętli, asynchronizacja jest prawie zawsze lepsza, więc nie blokujesz pętli, nie jest to wcale odruchowa reakcja, po prostu standardowa praktyka dla węzła Dev. Powiedziałem już, że to zależy od wymagań i nie sądzę, że Q mówi coś o linii poleceń? Ogólnie rzecz biorąc, jeśli jest to część większego zestawu kodu (nie wyjaśnionego przez PO), wówczas obsługa błędów jest zawsze inteligentna i najlepsza praktyka. Zrzucanie śladu stosu jest w porządku dla deweloperów, ale bzdury dla wszystkich innych.
Julian Knight

23
async to technika współbieżności. Jeśli potrzebujesz współbieżności, asynchronizacja jest wymagana, aby węzeł działał poprawnie (a nie „lepiej”). Jeśli nie masz współbieżności, nie potrzebujesz asynchronizacji. Chodzi o to, że musisz naprawdę zrozumieć, co robi async i dlaczego. Nie jest z natury „lepsze” bez powodu i nie musisz zapamiętywać tego jako „najlepszej praktyki”. Jeśli OP pisze narzędzie wiersza poleceń, aby zmienić plik JSON, a następnie zakończ, asynchronizacja komplikuje kod bez powodu, ponieważ współbieżność nie jest wymagana.
Peter Lyons,

Buduję narzędzie wiersza poleceń węzła. Jeśli nie zostanie zsynchronizowany, plik może zostać zablokowany, gdy dane wyjściowe mojego narzędzia zostaną powiązane z następnym narzędziem. Synchronizacja ma bardzo dobre powody. I dobre powody, by używać async.
TamusJRoyce

3

Oprócz poprzedniej odpowiedzi dodaj katalog ścieżki pliku dla operacji zapisu

 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

Dla tych, którzy chcą dodać element do kolekcji 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

Zdecydowanie odradzałbym używanie funkcji synchronicznych (blokujących), ponieważ zawierają one inne operacje współbieżne . Zamiast tego użyj asynchronicznych obietnic FS :

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

Pamiętaj, że setValuezwraca oczekującą obietnicę, musisz użyć funkcji .then lub, w ramach funkcji asynchronicznych, operatora 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

Zapisz dane po zakończeniu zadania

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!');
          });
        }
      });
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.