Tengo que analizar un archivo JSON que tiene muchos objetos pero ninguna estructura para el archivo. Se parece a esto:

{"obj1": "john"}
{"obj2": "sally"}
{"obj3": "veronica"}

Cada objeto está encendido por sí mismo, no hay contenedor. Entonces, cuando abro el archivo e intento recorrerlo, aparece el error Unexpected token { in JSON

Además de envolver los objetos en una matriz y luego revisar manualmente todo el archivo para agregar comas, ¿cómo puedo analizar esto?

0
Phil Andrews 20 mar. 2017 a las 21:39

2 respuestas

La mejor respuesta

Si realmente es un objeto por línea, es bastante sencillo tomar la cadena, dividirla en líneas y JSON.parse cada línea:

const str =
  '{"obj1": "john"}\n' +
  '{"obj2": "sally"}\n' +
  '{"obj3": "veronica"}';

const array = str.split(/[\r\n]+/)
                 .map(entry => JSON.parse(entry));

console.log(array);

... pero suponiendo que realmente sea un objeto por línea.

Si está leyendo el archivo, no tiene que comenzar con todo en una cadena como se indica arriba; solo lea línea por línea como Kevin B señala.

(Dado que está utilizando Node, he utilizado con gusto las funciones ES2015 + anteriores ...)

2
2 revs 23 may. 2017 a las 10:30

Si asume que cada línea del archivo de entrada está completa, JSON independiente, entonces una estrategia dividir en líneas-luego-analizar-cada funciona bien.

Pero incluso si los datos no se limitan a una sola línea, no todos se pierden. Puede analizar heurísticamente el archivo. No es hipereficiente, pero a excepción de los archivos muy grandes, probablemente nunca sepas la diferencia:

function incrementallyParseJSON(filepath) {
    var lines = fs.readFileSync(filepath)
                  .toString()
                  .split(/\n/g);
    var result = [];
    var [start, stop] = [0, 1];
    while (stop <= lines.length) {
        try { 
            var part = JSON.parse(lines.slice(start, stop).join('\n'));
            result.push(part);
            [start, stop] = [stop, stop+1]; 
        } catch (e) {
            stop += 1;
        }
    }
    return result;
}

Entonces, si su archivo es:

{"obj1": "john"}
{"obj2": "sally",
 "more": "other"}
{"obj3": "veronica"}
"something"
12

El resultado será:

[ { obj1: 'john' },
  { obj2: 'sally', more: 'other' },
  { obj3: 'veronica' },
  'something',
  12 ]

Ejemplo:

function incrementallyParseJSON(str) {
    var lines = str.split(/\n/g);
    var result = [];
    var [start, stop] = [0, 1];
    while (stop <= lines.length) {
        try { 
            var part = JSON.parse(lines.slice(start, stop).join('\n'));
            result.push(part);
            [start, stop] = [stop, stop+1]; 
        } catch (e) {
            stop += 1;
        }
    }
    return result;
}
var str =
  '{"obj1": "john"}\n' +
  '{"obj2": "sally",\n' +
  ' "more": "other"}\n' +
  '{"obj3": "veronica"}\n' +
  '"something"\n' +
  '12';

console.log(incrementallyParseJSON(str));
1
T.J. Crowder 20 mar. 2017 a las 19:28