Używając Node.JS, w jaki sposób odczytać plik JSON do pamięci (serwera)?

618

tło

Robię eksperymenty z Node.js i chciałbym odczytać obiekt JSON, albo z pliku tekstowego, albo z pliku .js (co jest lepsze?) Do pamięci, aby szybko uzyskać dostęp do tego obiektu z kodu. Zdaję sobie sprawę, że istnieją takie rzeczy jak Mongo, Alfred itp., Ale nie jest to teraz potrzebne.

Pytanie

Jak odczytać obiekt JSON z pliku tekstowego lub pliku js i do pamięci serwera za pomocą JavaScript / Node?

Matt Cashatt
źródło
1
jak nazywacie pamięć serwera? twój skrypt nodejs będzie działał, dopóki go uruchomisz, ale będziesz musiał gdzieś przechowywać dane, chyba że uczynisz go trwałym.
mpm

Odpowiedzi:

1205

Synchronizacja:

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));

Asynchronizacja:

var fs = require('fs');
var obj;
fs.readFile('file', 'utf8', function (err, data) {
  if (err) throw err;
  obj = JSON.parse(data);
});
Mihai
źródło
15
Myślę, że JSON.parse jest synchroniczny, bezpośrednio z wersji 8, co oznacza, że ​​nawet przy użyciu metody Async ludzie muszą uważać na duże pliki JSON. ponieważ wiązałoby to węzeł.
Sean_A91
25
Dla kompletności. Ich istnieje npm o nazwie jsonfile .
Stefan
5
Nie mogę uwierzyć, że tak trudno było znaleźć tę prostą rzecz. Każda odpowiedź, którą otrzymałem od Google,
zawierała żądanie HTTP,
6
dwa punkty: (1) Odpowiedź synchroniczna powinna po prostu być let imported = require("file.json"). (2) JSON.parse musi być asynchroniczny, ponieważ użyłem tego kodu do załadowania pliku JSON 70mb do pamięci jako obiektu. W ten sposób zabiera to milisekundy, ale jeśli require()go użyję , to będzie się dłubał .
Kyle Baker
8
Dla osób, które znajdą tę odpowiedź w 2019 r. I później, Node.js ma natywną obsługę JSON dla wielu, wielu wersji require, z tą odpowiedzią nie ma już zastosowania, jeśli chcesz tylko załadować plik JSON. Po prostu używaj let data = require('./yourjsonfile.json')i gotowe (z przypisem, że jeśli wydajność wymaga wpływa na kod, masz problemy znacznie wykraczające poza „chęć załadowania pliku .json”)
Mike 'Pomax' Kamermans
392

Najłatwiejszym sposobem, jaki to zrobiłem, jest po prostu użycie requirei ścieżka do pliku JSON.

Załóżmy na przykład, że masz następujący plik JSON.

test.json

{
  "firstName": "Joe",
  "lastName": "Smith"
}

Następnie możesz łatwo załadować to do aplikacji node.js za pomocą require

var config = require('./test.json');
console.log(config.firstName + ' ' + config.lastName);
Travis Tidwell
źródło
35
Tak, żeby ludzie wiedzieli i jeśli dobrze pamiętam, requirew węźle działa synchronicznie. Nurkowania w głębokim tutaj
prasanthv
@Ram Działa dla mnie, być może Twoja lokalizacja test.jsonbędzie inna niż jego przykład. Używamnode 5.0
guleria
18
Innym problemem / korzyścią
związaną
13
„Wymagaj” służy do ładowania modułów lub pliku konfiguracyjnego, którego używasz przez cały okres użytkowania aplikacji. wydaje się niewłaściwe używanie tego do ładowania plików.
Yaki Klein
2
Powiedziałbym, że jest to potencjalnie zagrożenie bezpieczeństwa. Jeśli ładowany plik json zawiera kod JS, czy requireuruchomiłby ten kod? Jeśli tak, to naprawdę musisz kontrolować, skąd pochodzą pliki json, w przeciwnym razie osoba atakująca może uruchomić złośliwy kod na komputerze.
sokkyoku,
57

Asynchroniczny jest z jakiegoś powodu! Rzuca kamień w @mihai

W przeciwnym razie oto kod, którego używał w wersji asynchronicznej:

// Declare variables
var fs = require('fs'),
    obj

// Read the file and send to the callback
fs.readFile('path/to/file', handleFile)

// Write the callback function
function handleFile(err, data) {
    if (err) throw err
    obj = JSON.parse(data)
    // You can now play with your datas
}
Florian Margaine
źródło
9
zgodził się :), dodał również asynchronię
mihai,
1
Świetnie :-) Nie lubię jednak wbudowanych wywołań zwrotnych, może to prowadzić do koszmarów wywołania zwrotnego, których wolałbym uniknąć.
Florian Margaine
9
Jest tam z jakiegoś powodu ... chyba że chcesz synchronicznie.
Matt Stephens
40

Przynajmniej w Node v9.9.1 możesz to zrobić

var json_data = require('/path/to/local/file.json');

i uzyskaj dostęp do wszystkich elementów obiektu JSON.

Alex Eftimiades
źródło
5
To podejście ładuje plik tylko raz. Jeśli zmienisz file.jsonpo nowym wymaganiu (bez ponownego uruchamiania programu), dane będą od pierwszego ładowania. Nie mam źródła, aby to poprzeć, ale miałem to w aplikacji, którą
buduję
Twoja odpowiedź jest żałośnie niepełna. To, co cię dostaje, to obiekt i nawet nie przeszkadza mu to w implementacji tostring ().
David A. Gray,
3
@ DavidA.Gray Pytanie chce mieć dostęp do obiektów jako obiektów, a nie ciągów. Oprócz pojedynczego wydania Lukas wspomniał, że odpowiedź jest w porządku.
mikemaccana
2
Użycie wymagania spowoduje również wykonanie dowolnego kodu w pliku. Ta metoda jest niepewna i odradzam jej stosowanie.
spoulson
16

W węźle 8 możesz użyć wbudowanego, util.promisify()aby asynchronicznie odczytać taki plik

const {promisify} = require('util')
const fs = require('fs')
const readFileAsync = promisify(fs.readFile)

readFileAsync(`${__dirname}/my.json`, {encoding: 'utf8'})
  .then(contents => {
    const obj = JSON.parse(contents)
    console.log(obj)
  })
  .catch(error => {
    throw error
  })
JP
źródło
3
.readFilejest już asynchroniczny, jeśli szukasz wersji synchronizacji, jej nazwa to .readFileSync.
Aternus
Jeśli chcesz korzystać z obietnic, istnieje również fs/promisesod Węzła 10. Uwaga: interfejs API jest eksperymentalny: nodejs.org/api/fs.html#fs_fs_promises_api
aboutaaron
@Aternus .readFilejest asynchroniczny , ale nie async. Oznacza to, że funkcja nie jest zdefiniowana asyncsłowem kluczowym, ani nie zwraca obietnicy, więc nie możesz tego zrobićawait fs.readFile('whatever.json');
Kip
@Kip co powiesz na CodeSandBox?
Aternus,
7

using node-fs-extra (async oczekuje)

const readJsonFile = async () => {
  try {
    const myJsonObject = await fs.readJson('./my_json_file.json');
    console.log(myJsonObject);
  } catch (err) {
    console.error(err)
  }
}

readJsonFile() // prints your json object
ifelse.codes
źródło
6

Korzystanie z pakietu fs-extra jest dość proste:

Synchronizacja:

const fs = require('fs-extra')

const packageObj = fs.readJsonSync('./package.json')
console.log(packageObj.version) 

Asynchronizacja:

const fs = require('fs-extra')

const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) 
Arturo Menchaca
źródło
3
function parseIt(){
    return new Promise(function(res){
        try{
            var fs = require('fs');
            const dirPath = 'K:\\merge-xml-junit\\xml-results\\master.json';
            fs.readFile(dirPath,'utf8',function(err,data){
                if(err) throw err;
                res(data);
        })}
        catch(err){
            res(err);
        }
    });
}

async function test(){
    jsonData = await parseIt();
    var parsedJSON = JSON.parse(jsonData);
    var testSuite = parsedJSON['testsuites']['testsuite'];
    console.log(testSuite);
}

test();
Satyabrata Saha
źródło
0

Tak wiele odpowiedzi i nikt nigdy nie przeprowadził testu porównawczego synchronizacji z asynchronizacją z wymaganiem. Opisałem różnicę w przypadkach korzystania z czytania json w pamięci poprzez wymagać, readFileSync i readfile tutaj .

Jehy
źródło
-1

Jeśli szukasz kompletnego rozwiązania do Asyncładowania pliku JSON Relative Pathz obsługą błędów

  // Global variables
  // Request path module for relative path
    const path = require('path')
  // Request File System Module
   var fs = require('fs');


// GET request for the /list_user page.
router.get('/listUsers', function (req, res) {
   console.log("Got a GET request for list of users");

     // Create a relative path URL
    let reqPath = path.join(__dirname, '../mock/users.json');

    //Read JSON from relative path of this file
    fs.readFile(reqPath , 'utf8', function (err, data) {
        //Handle Error
       if(!err) {
         //Handle Success
          console.log("Success"+data);
         // Parse Data to JSON OR
          var jsonObj = JSON.parse(data)
         //Send back as Response
          res.end( data );
        }else {
           //Handle Error
           res.end("Error: "+err )
        }
   });
})

Struktura katalogów:

wprowadź opis zdjęcia tutaj

Hitesh Sahu
źródło