Найти строки JSON в строке

Я ищу способ найти данные JSON в строке. Подумайте об этом, например, о коротких кодах Wordpress. Я считаю, что лучший способ сделать это - это регулярное выражение. Я не хочу разбирать JSON, просто найти все вхождения.

Есть ли способ в регулярном выражении иметь соответствующие числа скобок? В настоящее время я сталкиваюсь с этой проблемой при наличии вложенных объектов.

Быстрый пример демонстрации:

This is a funny text about stuff,
look at this product {"action":"product","options":{...}}.
More Text is to come and another JSON string
{"action":"review","options":{...}}

В результате я хотел бы иметь две строки JSON. Благодарю!

Ответы

Ответ 1

Извлечение строки JSON из заданного текста

Поскольку вы ищете упрощенное решение, вы можете использовать следующее регулярное выражение, которое использует рекурсию для решения проблемы соответствия набора круглых скобок. Он соответствует всем значениям между { и } рекурсивно.

Хотя, вы должны отметить, что это не гарантирует работу со всеми возможными случаями. Он служит только быстрым методом извлечения JSON-строк.

$pattern = '
/
\{              # { character
    (?:         # non-capturing group
        [^{}]   # anything that is not a { or }
        |       # OR
        (?R)    # recurses the entire pattern
    )*          # previous group zero or more times
\}              # } character
/x
';

preg_match_all($pattern, $text, $matches);
print_r($matches[0]);

Вывод:

Array
(
    [0] => {"action":"product","options":{...}}
    [1] => {"action":"review","options":{...}}
)

Демо-версия Regex101


Проверка строк JSON

В PHP единственный способ узнать, является ли JSON-строка действительной, - это применить json_decode(). Если парсер понимает JSON-строку и соответствует определенным стандартам, json_decode() создаст представление объекта/массива строки JSON.

Если вы хотите отфильтровать те, которые не являются допустимыми JSON, вы можете использовать array_filter() с функцией обратного вызова:

function isValidJSON($string) {
    json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE);
}

$valid_jsons_arr = array_filter($matches[0], 'isValidJSON');

Демо-версия