Как json_decode недействительный JSON с апострофом вместо кавычки

Образец кода:

<?php $json = "['foo', 'bar']"; var_dump( json_decode($json) ); 

Он работает с PHP 5.5.3, но он не подходит для более низких версий PHP

Он работает на моей машине с PHP 5.5.3, но это не везде.

Я знаю, что это неправильно JSON, но мой вебсервис дает мне JSON с символами вместе с "

 ['foo', "bar", {'test': "crazy \"markup\""}] 

песочница

Как анализировать данные JSON с апострофами в PHP 5.3? Очевидно, что оригинальный JSON, который я хочу разобрать, сложнее.

(Я не могу обновить свой PHP на рабочем сервере, не получив должного JSON от webservice)

Вот альтернативное решение этой проблемы:

 function fixJSON($json) { $regex = <<<'REGEX' ~ "[^"\\]*(?:\\.|[^"\\]*)*" (*SKIP)(*F) | '([^'\\]*(?:\\.|[^'\\]*)*)' ~x REGEX; return preg_replace_callback($regex, function($matches) { return '"' . preg_replace('~\\\\.(*SKIP)(*F)|"~', '\\"', $matches[1]) . '"'; }, $json); } 

Этот подход более устойчив, чем функция h2ooooooo в двух отношениях:

  • Он сохраняет двойные кавычки, встречающиеся в одной кавычной строке, путем применения к ним дополнительных экранов. Вместо этого вариант h2o заменит их двойными кавычками, тем самым изменив значение строки.
  • Он будет правильно обрабатывать экранированные двойные кавычки \" , для которых версия h2o, кажется, переходит в бесконечный цикл.

Контрольная работа:

 $brokenJSON = <<<'JSON' ['foo', {"bar": "hel'lo", "foo": 'ba"r ba\"z', "baz": "wor\"ld ' test"}] JSON; $fixedJSON = fixJSON($brokenJSON); $decoded = json_decode($fixedJSON); var_dump($fixedJSON); print_r($decoded); 

Вывод:

 string(74) "["foo", {"bar": "hel'lo", "foo": "ba\"r ba\"z", "baz": "wor\"ld ' test"}]" Array ( [0] => foo [1] => stdClass Object ( [bar] => hel'lo [foo] => ba"r ba"z [baz] => wor"ld ' test ) ) 

Вот простой парсер, который исправит ваши кавычки для вас. Если он встречает ' цитату, которая не входит в двойную кавычку " , она предположит, что это неправильно, и замените двойные кавычки внутри этой цитаты и включите цитату в двойные кавычки:

Пример :

 <?php function fixJSON($json) { $newJSON = ''; $jsonLength = strlen($json); for ($i = 0; $i < $jsonLength; $i++) { if ($json[$i] == '"' || $json[$i] == "'") { $nextQuote = strpos($json, $json[$i], $i + 1); $quoteContent = substr($json, $i + 1, $nextQuote - $i - 1); $newJSON .= '"' . str_replace('"', "'", $quoteContent) . '"'; $i = $nextQuote; } else { $newJSON .= $json[$i]; } } return $newJSON; } $brokenJSON = "['foo', {\"bar\": \"hel'lo\", \"foo\": 'ba\"r'}]"; $fixedJSON = fixJSON( $brokenJSON ); var_dump($fixedJSON); print_r( json_decode( $fixedJSON ) ); ?> 

Выход :

 string(41) "["foo", {"bar": "hel'lo", "foo": "ba'r"}]" Array ( [0] => foo [1] => stdClass Object ( [bar] => hel'lo [foo] => ba'r ) ) 

DEMO

Одним из решений было бы создание прокси-сервера с использованием NodeJS. NodeJS будет обрабатывать неисправный JSON просто отлично и вернуть чистую версию:

 johan:~ # node > JSON.stringify(['foo', 'bar']); '["foo","bar"]' 

Возможно, напишите простой сценарий Node, который принимает данные JSON как STDIN и возвращает проверенный JSON в STDOUT. Таким образом, вы можете вызвать его из PHP.

Недостатком является то, что вашему серверу потребуется NodeJS. Не уверен, что это проблема для вас.

Ответ NikiCs уже занят . Кажется, что ваш ввод создается вручную, поэтому вполне возможно, что в ' одиночных кавычках» вы получите недоказуемые " двойники». Поэтому утверждение регулярного выражения рекомендуется вместо простого поиска и замены.

Но есть также несколько пользовательских JSON-парсеров, которые поддерживают немного больше синтаксиса выражения Javascript. На данный момент лучше всего говорить об JSOL , объектных литералах JavaScript.

PEARs Services_JSON

Services_JSON может декодировать:

  • ключи без кавычек
  • и строки, заключенные в одинарные кавычки.

Дополнительные параметры не требуются, just = (new Services_JSON)->decode($jsol);

up_json_decode () в upgradephp

Фактически это означало возврат к ранним версиям PHP без расширения JSON. Он обновляет json_decode() . Но есть также версия upgrade.php.prefixed , которую вы будете использовать здесь.
Он вводит дополнительный флаг JSON_PARSE_JAVASCRIPT .

 up_json_decode($jsol, false, 512, JSON_PARSE_JAVASCRIPT); 

И я полностью забыл о написании этого, но также поддерживает строки с одним кавычком.
Например:

 { num: 123, "key": "value", 'single': 'with \' and unquoted " dbls' } 

Будет расшифровываться:

 stdClass Object ( [num] => 123 [key] => value [single] => with ' and unquoted " double quotes ) 

Очевидно, что парсер в userland заметно медленнее, чем просто обработка некорректного JSON. Если вы не ожидаете дальнейших ошибок в своем веб-сервисе, перейдите вместо преобразования котировки.

Если вы знаете, что PHP 5.5. + Будет разбирать этот JSON изящно, я бы передал ответы веб-службы через прокси-скрипт на веб-сервере PHP5.5 +, который санирует ответы для более низких версий – это означает только echo json_encode(json_decode($response)) ; Это стабильный и надежный подход.

Если URL-адрес веб-службы настраивается через значение конфигурации, он будет работать для более низких версий, обратившись к прокси-серверу, в более высоких версиях, напрямую обращаясь к веб-службе.

Вы могли бы использовать (и, возможно, модифицировать / расширять) библиотеку для создания AST из поставляемого JSON и заменять одинарные кавычки двойными кавычками.

https://github.com/Seldaek/jsonlint/blob/master/src/Seld/JsonLint/Lexer.php

Может быть, хорошее начало.

Быстрое решение может быть str_replace("'","\"",$string) . Это зависит от многих факторов, но я думаю, вы могли бы попробовать.