6

このデータを ajax レスポンスとして取得します。

{
    "idArray" = (
        "99516",
        "99518",
        "97344",
        "97345",
        "98425"
    );
    "frame" = {
        "size" = {
            "width" = "8";
            "height" = "8";
        };
        "origin" = {
            "x" = "244";
            "y" = "345";
        };
    };
},

これはデータの一部にすぎませんが、同じ形式で続きます。このデータを生成するファイルのソースにアクセスできません。

これは既知の形式ですか、それとも何かカスタムですか?

4

3 に答える 3

3

人々は、正規表現で解析できないもの (つまり、非正規言語) でさえも、すべてに正規表現を使用する傾向があるため、このデータ形式の概念実証パーサーを作成しました。

$input = '{
    "idArray" = (
        "99516",
        "99518",
        "97344",
        "97345",
        "98425"
    );
    "frame" = {
        "size" = {
            "width" = "8";
            "height" = "8";
        };
        "origin" = {
            "x" = "244";
            "y" = "345";
        };
    };
}';

echo json_encode(parse($input));

function parse($input) {
    $tokens = tokenize($input);
    $index = 0;
    $result = parse_value($tokens, $index);
    if ($result[1] !== count($tokens)) {
        throw new Exception("parsing stopped at token " . $result[1] . " but there is more input");
    }
    return $result[0][1];
}

function tokenize($input) {
    $tokens = array();
    $length = strlen($input);
    $pos = 0;
    while($pos < $length) {
        list($token, $pos) = find_token($input, $pos);
        $tokens[] = $token;
    }
    return $tokens;
}

function find_token($input, $pos) {
    $static_tokens = array("=", "{", "}", "(", ")", ";", ",");
    while(preg_match("/\s/mis", substr($input, $pos, 1))) { // eat whitespace
        $pos += 1;
    }
    foreach ($static_tokens as $static_token) {
        if (substr($input, $pos, strlen($static_token)) === $static_token) {
            return array($static_token, $pos + strlen($static_token));
        }
    }
    if (substr($input, $pos, 1) === '"') {
        $length = strlen($input);
        $token_length = 1;
        while ($pos + $token_length < $length) {
            if (substr($input, $pos + $token_length, 1) === '"') {
                return array(array("value", substr($input, $pos + 1, $token_length - 1)), $pos + $token_length + 1);
            }
            $token_length += 1;
        }
    }
    throw new Exception("invalid input at " . $pos . ": `" . substr($input, $pos - 10, 20) . "`");
}

// value is either an object {}, an array (), or a literal ""
function parse_value($tokens, $index) {
    if ($tokens[$index] === "{") {  // object: a list of key-value pairs, glued together by ";"
        $return_value = array();
        $index += 1;
        while ($tokens[$index] !== "}") {
            list($key, $value, $index) = parse_key_value($tokens, $index);
            $return_value[$key] = $value[1];
            if ($tokens[$index] !== ";") {
                throw new Exception("Unexpected: " . print_r($tokens[$index], true));
            }
            $index += 1;
        }
        return array(array("object", $return_value), $index + 1);
    }
    if ($tokens[$index] === "(") {  // array: a list of values, glued together by ",", the last "," is optional
        $return_value = array();
        $index += 1;
        while ($tokens[$index] !== ")") {
            list($value, $index) = parse_value($tokens, $index);
            $return_value[] = $value[1];
            if ($tokens[$index] === ",") {  // last, is optional
                $index += 1;
            } else {
                if ($tokens[$index] !== ")") {
                    throw new Exception("Unexpected: " . print_r($tokens[$index], true));
                }
                return array(array("array", $return_value), $index + 1);
            }
        }
        return array(array("array", $return_value), $index + 1);
    }
    if ($tokens[$index][0] === "value") {
        return array(array("string", $tokens[$index][1]), $index + 1);
    }
    throw new Exception("Unexpected: " . print_r($tokens[$index], true));
}

// find a key (string) followed by '=' followed by a value (any value)
function parse_key_value($tokens, $index) {
    list($key, $index) = parse_value($tokens, $index);
    if ($key[0] !== "string") { // key must be a string
        throw new Exception("Unexpected: " . print_r($key, true));
    }
    if ($tokens[$index] !== "=" ) {
        throw new Exception("'=' expected");
    }
    $index += 1;
    list($value, $index) = parse_value($tokens, $index);
    return array($key[1], $value, $index);
}

出力は次のとおりです。

{"idArray":["99516","99518","97344","97345","98425"],"frame":{"size":{"width":"8","height":"8"},"origin":{"x":"244","y":"345"}}}

ノート

  • 元の入力には末尾の,. そのキャラクターを削除しました。元に戻すと、エラー (さらに入力) がスローされます。

  • このパーサーは、解析を開始する前にすべての入力をトークン化するという意味で単純です。これは大きな入力には適していません。

  • トークナイザーで文字列のエスケープ検出を追加していません。のように: "foo\"bar"

これは楽しいエクササイズでした。ご不明な点がございましたら、お知らせください。

編集: これは JavaScript の質問です。PHP を JavaScript に移植するのはそれほど難しくありません。はlist($foo, $bar) = func()次と同等です。var res = func(); var foo = res[0]; var bar = res[1];

于 2014-12-17T13:58:22.047 に答える
1

応答テキストをパラメーターとしてこの関数を使用してみてください。

function getJsonData(str){
    str = str.replace(/,/g, '')         //remove ,
             .replace(/\(/g, '[')       //replace (
             .replace(/\[/g)', ']')     //replace )
             .replace(/;/g, ',')        //replace ; 
             .replace(/=/g, ':');       //replace :
    return JSON.parse(str);
}

これは @SamSal による編集です

function getJsonData(str){
    str = str.replace(/\(/g, '[')       //replace (
         .replace(/\)/g, ']')       //replace )
         .replace(/;\n\s+}/g, '}')  //replace ;} with }
         .replace(/;/g, ',')        //replace remaining ; with ,  
         .replace(/=/g, ':');       //replace :
    return JSON.parse(str);
}
于 2014-12-16T21:10:24.990 に答える
0

これは既知の形式ですか、それとも何かカスタムですか?

これはカスタム形式で、実際には JSONではありませんが、 JSONに少し似ています。

于 2014-12-17T14:14:55.447 に答える