Usando Node.JS, ¿cómo leo un archivo JSON en la memoria (del servidor)?

618

Antecedentes

Estoy experimentando con Node.js y me gustaría leer un objeto JSON, ya sea desde un archivo de texto o un archivo .js (¿cuál es mejor?) En la memoria para poder acceder a ese objeto rápidamente desde el código. Me doy cuenta de que hay cosas como Mongo, Alfred, etc., pero eso no es lo que necesito en este momento.

Pregunta

¿Cómo leo un objeto JSON de un archivo de texto o js y en la memoria del servidor usando JavaScript / Node?

Matt Cashatt
fuente
1
¿Cómo se llama la memoria del servidor? su script de nodejs funcionará mientras lo haga funcionar, pero tendrá que almacenar datos en algún lugar a menos que haga que el script de nodejs sea persistente.
mpm

Respuestas:

1205

Sincronización:

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

Asíncrono:

var fs = require('fs');
var obj;
fs.readFile('file', 'utf8', function (err, data) {
  if (err) throw err;
  obj = JSON.parse(data);
});
mihai
fuente
15
Creo que JSON.parse es sincrónico, es directamente desde v8, lo que significa que incluso con la forma Async, las personas deben tener cuidado con los grandes archivos JSON. ya que ataría el nodo.
Sean_A91
25
En aras de la exhaustividad. Existe un npm llamado jsonfile .
Stefan
55
No puedo creer que fuera tan difícil encontrar esta cosa simple. Cada respuesta que recibí de Google fue hacer una HTTPRequest o usar JQuery o hacerlo en el navegador
juliangonzalez
66
dos puntos: (1) La respuesta sincrónica debería ser simplemente let imported = require("file.json"). (2) JSON.parse debe ser asíncrono, porque utilicé este código para cargar un archivo JSON de 70mb en la memoria como un objeto. Lleva milisegundos de esta manera, pero si lo uso require(), funciona .
Kyle Baker,
8
Para las personas que encuentran esta respuesta en 2019 y en adelante, Node.js ha tenido soporte nativo de json para muchas, muchas versiones require, con esta respuesta ya no es aplicable si solo desea cargar un archivo json. Simplemente utilícelo let data = require('./yourjsonfile.json')y listo (con la nota de libro de que si el rendimiento de require está afectando su código, tiene problemas mucho más allá de "querer cargar un archivo .json")
Mike 'Pomax' Kamermans
392

La forma más fácil que he encontrado para hacer esto es simplemente usar requirey la ruta a su archivo JSON.

Por ejemplo, suponga que tiene el siguiente archivo JSON.

test.json

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

Luego puede cargar esto fácilmente en su aplicación node.js usando require

var config = require('./test.json');
console.log(config.firstName + ' ' + config.lastName);
Travis Tidwell
fuente
35
Solo para que la gente sepa, y si no recuerdo mal, requireen el nodo se ejecuta sincrónicamente. Sumérgete en lo profundo aquí
prasanthv
@Ram Funciona para mí, puede ser que su ubicación test.jsonsea ​​diferente de su ejemplo. Estoy usandonode 5.0
guleria
18
Otro tema / beneficio con estos métodos es el hecho de que los datos requeridos se almacena en caché a menos que elimine específicamente la instancia en caché
magicode118
13
"require" está destinado a ser usado para cargar módulos o archivos de configuración que está utilizando durante la vida útil de su aplicación. no parece correcto usar esto para cargar archivos.
Yaki Klein
2
Yo diría que esto es potencialmente una amenaza para la seguridad. Si el archivo json que está cargando contiene código JS, ¿ requireejecutaría ese código? Si es así, realmente necesita controlar de dónde provienen sus archivos json o un atacante podría ejecutar código malicioso en su máquina.
sokkyoku
57

Asíncrono está ahí por una razón! Lanza piedra a @mihai

De lo contrario, aquí está el código que utilizó con la versión asincrónica:

// 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
fuente
99
estuvo de acuerdo :), agregó asíncrono también
mihai
1
Genial :-) Sin embargo, no me gustan las devoluciones de llamadas en línea, puede provocar pesadillas de devolución de llamadas que prefiero evitar.
Florian Margaine
99
Está ahí por una razón ... a menos que lo desee sincrónicamente.
Matt Stephens
40

Al menos en el Nodo v8.9.1, solo puedes hacer

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

y acceder a todos los elementos del objeto JSON.

Alex Eftimiades
fuente
55
Este enfoque carga el archivo solo una vez. Si va a cambiar los datos file.jsonrequeridos después de nuevo (sin reiniciar el programa), los datos serán de la primera carga. No tengo fuente para respaldar esto, pero tenía esto en la aplicación que estoy construyendo
Lukas Ignatavičius
Su respuesta es lamentablemente incompleta. Lo que eso te atrapa es un objeto, y ni siquiera se molesta en implementar tostring ().
David A. Gray
3
@ DavidA.Gray La pregunta quiere poder acceder a los objetos como objetos, no como cadenas. Aparte del tema singleton, Lukas mencionó que esta respuesta está bien.
mikemaccana
2
El uso de require también ejecutará código arbitrario en el archivo. Este método es inseguro y recomendaría no hacerlo.
spoulson
16

En el Nodo 8, puede usar el incorporado util.promisify()para leer asíncronamente un archivo como este

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
fuente
3
.readFileya es asíncrono, si está buscando la versión de sincronización, su nombre es .readFileSync.
Aternus
Si desea usar promesas, también existe a fs/promisespartir del Nodo 10. Nota: la API es experimental: nodejs.org/api/fs.html#fs_fs_promises_api
aboutaaron el
@Aternus .readFilees asíncrono , pero no async. Es decir, la función no está definida con la asyncpalabra clave, ni devuelve una Promesa, por lo que no puede hacerloawait fs.readFile('whatever.json');
Kip
@Kip ¿qué tal un CodeSandBox?
Aternus
7

usando node-fs-extra (espera asíncrona)

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
fuente
6

Usar el paquete fs-extra es bastante simple:

Sincronización:

const fs = require('fs-extra')

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

Asíncrono:

const fs = require('fs-extra')

const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) 
Arturo Menchaca
fuente
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
fuente
0

Tantas respuestas, y nadie jamás hizo un punto de referencia para comparar sincronización vs asíncrono vs requerimiento. Describí la diferencia en los casos de uso de leer json en la memoria a través de require, readFileSync y readFile aquí .

Jehy
fuente
-1

Si está buscando una solución completa para Asynccargar un archivo JSON Relative Pathcon Manejo de errores

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

Estructura de directorios:

ingrese la descripción de la imagen aquí

Hitesh Sahu
fuente