Вы не можете использовать регулярное выражение для извлечения JSON из произвольного текста. Так как регулярные выражения обычно not powerful enough to validate JSON (если вы не можете использовать PCRE), они также не могут сравниться с ним - если бы они могли, они могли бы также проверить JSON.
Однако, если вы знаете, что элемент верхнего уровня вашего JSON всегда объект или массив, вы можете перейти на следующий подход:
- Найти первое отверстие (
{
или [
) и последний закрытие (}
или ]
) скобка в вашей строке.
- Попробуйте разобрать этот текст (включая фигурные скобки) с помощью
JSON.parse()
. Если это удалось, закончить и вернуть результат анализа.
- Возьмите предыдущую закрывающую фигуру и попробуйте разобрать эту строку. Если это удастся, вы закончите снова.
- Повторяйте это до тех пор, пока не получите скобу или ту, которая находится перед текущей открытой скобой.
- Найдите первую открывающую скобку после первой с шага 1. Если вы ее не нашли, строка не содержит объект/массив JSON, и вы можете остановиться.
- Перейти к шагу 2.
Вот функция, которая извлекает объект JSON и возвращает объект и его позицию. Если вам действительно нужны массивы верхнего уровня, тоже, должно быть, чтобы расширить:
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 (выполняется в среде nodejs, но должны работать в браузере, тоже): https://paste.aeum.net/show/81/
Вы здесь не новичок. Что вы пробовали? Как выглядит ваш ответ? –
Кроме того, RegEx, вероятно, не является правильным инструментом для работы. –
@Truth Моим единственным обходным решением до сих пор является включение маркеров в текст ответа, чтобы показать начало и конец строки JSON. Ничто не может гордиться, или это будет направлять ответ. – Christophe