Escribe objetos en un archivo con Node.js

83

He buscado esto en todo stackoverflow / google, pero parece que no puedo resolverlo.

Estoy raspando enlaces de redes sociales de una página URL determinada y la función devuelve un objeto con una lista de URL.

Cuando intento escribir estos datos en un archivo diferente, los resultados en el archivo en [object Object]lugar de lo esperado: [' https://twitter.com/#!/101Cookbooks ', ' http://www.facebook.com/ 101cookbooks '] como lo hace cuando veo console.log()los resultados.

Este es mi triste intento de leer y escribir un archivo en Node, tratando de leer cada línea (la url) e ingresar a través de una llamada de función request(line, gotHTML):

fs.readFileSync('./urls.txt').toString().split('\n').forEach(function (line){
    console.log(line); 
    var obj = request(line, gotHTML); 
    console.log(obj); 
    fs.writeFileSync('./data.json', obj , 'utf-8'); 
});   

para referencia - la gotHTMLfunción:

function gotHTML(err, resp, html){ 
    var social_ids = []; 

    if(err){
        return console.log(err); 
    } else if (resp.statusCode === 200){ 
        var parsedHTML = $.load(html); 

        parsedHTML('a').map(function(i, link){
            var href = $(link).attr('href');
            for(var i=0; i<socialurls.length; i++){
                if(socialurls[i].test(href) && social_ids.indexOf(href) < 0 ) {
                    social_ids.push(href); 
                }; 
            }; 
        })
    };

    return social_ids;
};
Sarahbkim
fuente
3
[object Object]es un objeto toString. Si desea la representación del objeto, utilice JSON.stringify.
elclanrs
2
Tenga cuidado con JSON.stringify. Con las matrices, está a salvo, pero cuando los objetos tienen referencias circulares, fallarán ( consulte este tema ). El utilmódulo maneja referencias circulares.
Jim Schubert

Respuestas:

71

obj es una matriz en su ejemplo.

fs.writeFileSync (nombre de archivo, datos, [opciones]) requiere Stringo Bufferen el parámetro de datos. ver docs .

Intente escribir la matriz en formato de cadena:

// writes 'https://twitter.com/#!/101Cookbooks', 'http://www.facebook.com/101cookbooks'
fs.writeFileSync('./data.json', obj.join(',') , 'utf-8'); 

O:

// writes ['https://twitter.com/#!/101Cookbooks', 'http://www.facebook.com/101cookbooks']
var util = require('util');
fs.writeFileSync('./data.json', util.inspect(obj) , 'utf-8');

editar: La razón por la que ve la matriz en su ejemplo es porque la implementación del nodo de console.logno solo llama toString, llama a util.format ver la fuente de console.js

Jim Schubert
fuente
5
Si su objeto contiene matrices grandes, esto no funcionará ya que el método de inspección generará algo como "45000 más ...]"
Coxer
96

Sobre la base de lo que deb2fast dijo, también pasaría un par de parámetros adicionales a JSON.stringify () para obtener un formato bonito:

fs.writeFileSync('./data.json', JSON.stringify(obj, null, 2) , 'utf-8');

El segundo parámetro es una función de reemplazo opcional que no necesita en este caso, por lo que nullfunciona.

El tercer parámetro es el número de espacios a usar para la sangría. 2 y 4 parecen ser opciones populares.

Chico
fuente
va a causar un problema de dependencia circular. Las dependencias bidireccionales no se pudieron convertir a JSON.
Ozan Ertürk
Al archivo de texto escrito le falta el carácter de nueva línea al final del archivo. Cualquier forma de arreglar esto?
friederbluemle
1
@friederbluemle: podría + '\n'usar esa llamada a stringify () para agregar esa nueva línea.
Guy
1
Este funcionó mejor para mí porque usar la respuesta aceptada me dio un resultado incorrecto.
Anshuman Kumar
20

Si está obteniendo [object object], useJSON.stringify

fs.writeFile('./data.json', JSON.stringify(obj) , 'utf-8');

Funcionó para mí.

deb2fast
fuente
10

En mi experiencia, JSON.stringify es un poco más rápido que util.inspect. Tuve que guardar el objeto de resultado de una consulta de DB2 como un archivo json, la consulta devolvió un objeto de 92k filas, la conversión tardó mucho en completarse con util.inspect, así que hice la siguiente prueba escribiendo el mismo objeto de 1000 registros a un archivo con ambos métodos.

  1. JSON.Stringify

    fs.writeFile('./data.json', JSON.stringify(obj, null, 2));
    

Tiempo: 3:57 (3 min 57 seg)

Formato de resultado:

[
  {
    "PROB": "00001",
    "BO": "AXZ",
    "CNTRY": "649"
   },
  ...
]
  1. util.inspect

    var util = require('util');
    fs.writeFile('./data.json', util.inspect(obj, false, 2, false));
    

Tiempo: 4:12 (4 min 12 seg)

Formato de resultado:

[ { PROB: '00001',
    BO: 'AXZ',
    CNTRY: '649' },
    ...
]
Netsmile
fuente
4

¿podría intentar hacer JSON.stringify (obj);

Me gusta esto

 var stringify = JSON.stringify(obj);
fs.writeFileSync('./data.json', stringify , 'utf-8'); 
Navvye Anand
fuente
1

En caso de que alguien más se encuentre con esto, utilizo la biblioteca fs-extra en el nodo y escribo objetos javascript en un archivo como este:

const fse = require('fs-extra');
fse.outputJsonSync('path/to/output/file.json', objectToWriteToFile); 
tljw86
fuente