1

私は問題があります。間違いのために、次のような無効な 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"
    }
}

ご覧のとおり、フィールド Description には不正な文字列 (" into ") が含まれているため、php の json_decode を使用して json を解析できません。実際には NULL が返されます。これよりもはるかに大きい100万の間違ったjsonがあります(10倍)。どうすればphpでできますか?

4

1 に答える 1

1

あなたの場合、json の文字列が 1 行を超えることができないという事実を利用できます。これは、複数行に対応した検索でつかみ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
        )

)
于 2012-11-07T15:25:39.460 に答える