No puede usar una expresión regular para extraer JSON de un texto arbitrario. Como las expresiones regulares generalmente son not powerful enough to validate JSON (a menos que pueda usar PCRE), tampoco pueden coincidir; si pudieran, también podrían validar JSON.
Sin embargo, si se sabe que el elemento de nivel superior de su JSON es siempre un objeto o una matriz, se puede ir por el siguiente enfoque:
- encontrar la primera abertura (
{
o [
) y el último cierre (}
o ]
) abrazadera en su cadena.
- Trate de analizar ese bloque de texto (incluidos los paréntesis) usando
JSON.parse()
. Si tuvo éxito, finaliza y devuelve el resultado analizado.
- Tome la llave de cierre anterior e intente analizar esa cadena. Si tiene éxito, has terminado de nuevo.
- Repite esto hasta que no tengas ninguna llave o una que venga antes de la abrazadera de apertura actual.
- Busque la primera abrazadera de apertura después de la del paso 1. Si no encontró ninguna, la cadena no contiene un objeto/matriz JSON y puede detenerse.
- Ir al paso 2.
Aquí es una función que extrae un objeto JSON y devuelve el objeto y su posición. Si realmente necesita arreglos de alto nivel, también, que debe ser ampliar:
function extractJSON(str) {
var firstOpen, firstClose, candidate;
firstOpen = str.indexOf('{', firstOpen + 1);
do {
firstClose = str.lastIndexOf('}');
console.log('firstOpen: ' + firstOpen, 'firstClose: ' + firstClose);
if(firstClose <= firstOpen) {
return null;
}
do {
candidate = str.substring(firstOpen, firstClose + 1);
console.log('candidate: ' + candidate);
try {
var res = JSON.parse(candidate);
console.log('...found');
return [res, firstOpen, firstClose + 1];
}
catch(e) {
console.log('...failed');
}
firstClose = str.substr(0, firstClose).lastIndexOf('}');
} while(firstClose > firstOpen);
firstOpen = str.indexOf('{', firstOpen + 1);
} while(firstOpen != -1);
}
var obj = {'foo': 'bar', xxx: '} me[ow]'};
var str = 'blah blah { not {json but here is json: ' + JSON.stringify(obj) + ' and here we have stuff that is } really } not ] json }} at all';
var result = extractJSON(str);
console.log('extracted object:', result[0]);
console.log('expected object :', obj);
console.log('did it work ?', JSON.stringify(result[0]) == JSON.stringify(obj) ? 'yes!' : 'no');
console.log('surrounding str :', str.substr(0, result[1]) + '<JSON>' + str.substr(result[2]));
Demo (ejecutado en el entorno nodejs, pero debería funcionar en un navegador, también): https://paste.aeum.net/show/81/
No eres nuevo aquí. ¿Qué has intentado? ¿Cómo es tu respuesta? –
Además, RegEx probablemente no sea la herramienta correcta para el trabajo. –
@Truth mi única solución hasta el momento es incluir marcadores en el texto de respuesta para mostrar el principio y el final de la cadena JSON. No hay nada de qué enorgullecerse o eso guiaría la respuesta. – Christophe