У меня проблема. Для ошибки у меня много недействительных строк JSON:
{ "d": { "results": [ { "__metadata": { "uri": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non supporting iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=0&$top=1", "type": "WebResult" }, "ID": "7858fc9f-6bd5-4102-a835-0fa89e9f992a", "Title": "something good", "Description": "something "WRONG" here!", "DisplayUrl": "www.devx.com/Java/Article/27685/1954", "Url": "http://www.devx.com/Java/Article/27685/1954" } ], "__next": "https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non%20supporting%20iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=50" } }
Как вы можете видеть, поле Описание содержит плохую строку («в»), поэтому я не могу разобрать json, используя json_decode php, infact возвращает NULL. У меня 1 миллион неправильных json, намного больше, чем это (10 раз). Как я могу сделать в php?
В вашем случае вы можете использовать тот факт, что строки в json не могли быть над линией. Это быстрый способ захватить многострочный поиск и заменить его регулярной функцией выражения, например preg_match_callback
в PHP.
/^\s+"[a-z_"]+": "([^"]*".*)",?$/mi
Пробел в начале строки; имя-член в виде допустимого имени (только символы и подчеркивание здесь) в виде строки; :
а затем сломанная строка до конца строки, а затем запятая,? ,
Это регулярное выражение уже соответствует только недопустимым строкам. Однако, если ваш json также содержит допустимую строку с \"
внутри, это регулярное выражение действительно не работает .
Поэтому также полезно разместить некоторые проверки, что замена будет делать то, что она предназначена.
$like = '... json-like but broken json string as in question ...'; // Fixing #1: member strings containing double-quotes on the same line. $fix1Pattern = '/^(\s+"[a-z_]+": ")([^"]*".*)(",?)$/mi'; $fix1Callback = function ($matches) { list($full, $prefix, $string, $postfix) = $matches; $fixed = strtr($string, ['"' => '\"']); if (!is_string(json_decode("\"$fixed\""))) { throw new Exception('Fix #1 did not work as intended'); } return "$prefix$fixed$postfix"; }; // apply fix1 onto the string $buffer = preg_replace_callback($fix1Pattern, $fix1Callback, $like); // test if it finally works print_r(json_decode($buffer));
Имейте в виду, что это ограничено. Возможно, вам нужно будет узнать о регулярных выражениях, которые сначала представляют собой мир. Но принцип часто очень похож: вы ищете строку для шаблонов, которые являются сломанными частями, а затем вы выполняете некоторые строковые манипуляции, чтобы исправить это.
Если строка json намного более сломанна, то это требует еще большей любви, возможно, ее легко решить с помощью обычного выражения.
Примерный вывод для примера кода и предоставленных данных:
stdClass Object ( [d] => stdClass Object ( [results] => Array ( [0] => stdClass Object ( [__metadata] => stdClass Object ( [uri] => https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non supporting iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=0&$top=1 [type] => WebResult ) [ID] => 7858fc9f-6bd5-4102-a835-0fa89e9f992a [Title] => something good [Description] => something "WRONG" here! [DisplayUrl] => www.devx.com/Java/Article/27685/1954 [Url] => http://www.devx.com/Java/Article/27685/1954 ) ) [__next] => https://api.datamarket.azure.com/Data.ashx/Bing/Search/Web?Query=u0027non%20supporting%20iframesu0027&Market=u0027it-ITu0027&Adult=u0027Offu0027&Options=u0027DisableLocationDetectionu0027&WebSearchOptions=u0027DisableQueryAlterationsu0027&$skip=50 ) )