2

ゴール:

  1. json_encodeプライベートプロパティを持つPHPオブジェクト
  2. jQueryを使用して低レベルAJAXを介してエンコードされたオブジェクトをデータ文字列として送信します
  3. json_decodeリクエストの送信先となるAJAXURLのPHPオブジェクト
  4. 勝つ

問題:

ステップ3で、json_last_errorは3(JSON_ERROR_CTRL_CHAR Control character error, possibly incorrectly encoded)を返します

クラス:

class Stream {
    private $limit;
    private $type;
    private $sort;
    private $offset=0;
    private $userID;
    private $catID;
    private $content = array();
    private $num_posts;

    function __construct(){
        $a = func_get_args();
        $i = func_num_args();
        if (method_exists($this,$f='__construct'.$i)) {
            call_user_func_array(array($this,$f),$a);
        }
    }

    function __construct5($limit, $type, $sort, $userID, $catID){
        $this->limit = $limit;
        $this->type = $type;
        $this->sort = $sort;
        $this->userID = $userID;
        $this->catID = $catID;
        //$this->num_posts = $this->retrieveTotal();

        //$this->setContent(); 
    }

    function __get($name) {
        if(isset($this->$name)){
            return $this->$name;
        }
    }

        public function encodeJSON(){
        foreach ($this as $key => $value){
            if($key != 'content'){
                $json->$key = $value;
            }
        }
        return json_encode($json);
    }

    public function decodeJSON($json_str){
        $json = json_decode($json_str, true);
        echo '<br>error: '.json_last_error();

        foreach ($json as $key => $value){
            $this->$key = $value;
        }
    }
}

//create the object to be encoded
$strm = new Stream(5, 'toc', ' ', 1, ' ');

/*this test works

$d=$strm->encodeJSON();

$st = new Stream();
$st->decodeJSON($d);
*/

AJAX関数:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    //load more posts
    $("#active").live("click", function() {
    var stream= '<?= $strm->encodeJSON();?>'; 
        var dataString = 'stream='+stream;
        var request = $.ajax({  
            type: "POST",  
            url: "ajax/loadmore.php",  
            data: dataString,
            beforeSend:function(data){
                $('.load-more').html('<img src="ajax/loader.gif" alt="Loading..." />');
            },
            success: function(html) {
                $('#active').remove();
                $('#stream').append(html);
            }
        });

        //ajax error reporting
        request.fail(function(jqXHR, textStatus) {
            $('#active').html(textStatus);
        });
    });
</script>

<a class='load-more' id='active'>load more posts</a>

AJAXリクエスト(loadmore.php):

require_once'../../classes/stream.class.php';
$strm = new Stream();
$strm->decodeJSON($_POST['stream']);

私が試したこと:

このコードスニペット

$d=$strm->encodeJSON();

$st = new Stream();
$st->decodeJSON($d);

正常に動作します。それは私にAJAXがデコードを妨害していると信じさせるでしょう。

私も変更を試み$json = json_decode($json_str, true);ましたが$json = json_decode(utf8_encode($json_str), true);、何も変更されません。

注:クラスプロパティを公開することを提案することは解決策ではありません

編集:文字列をエコーすると、{ "limit": "5", "type": "toc", "sort": " ", "offset": "0", "userID": "3", "catID": " ", "num_posts": "2" }decodeJSONに送信され、有効であるとテストされます

このスクリーンショットは、decodeJSON($ json_str)に送信されている引数$json_strとエラーコードを示しています。 json_strパラメータとエラー

4

3 に答える 3

3

の理由JSON_ERROR_CTRL_CHAR

返さJSON_ERROR_CTRL_CHARれる理由は、文字エンコーディング (つまり、utf8 または iso) によるものではありません。このエラーは、データが正しくエンコードされておらず、結果の文字列が有効な JSON ではない場合に発生します。'一重引用符と二重引用符を混在させる"と、エンコード プロセスにも干渉する可能性があるため、一貫性を保つことが重要です。

そうは言っても、
そもそも実際のデータを送信していないため、エラーが返される可能性が最も高くなります。リクエストを通じて空の文字列を送信しています。そうではありませんが、実際には文字列を送信しています

<?= $strm->encodeJSON();?>

その後、

json_encode("<?= $strm->encodeJSON();?>");

あなたのloadmore.phpで。<?php ?>ただし、何もエコーしていないため、正しいphpタグを使用した場合はとにかく空になります。

変化する

var stream= '<?= $strm->encodeJSON();?>';

適切なphpタグに追加し、実際に何かを出力することを確認してください。そうしないstreamと、空の文字列になります.

var stream= '<?php echo $strm->encodeJSON(); ?>';

そして、それは適切に機能するはずです。

その他

エンコードURIコンポーネント

一般に、AJAX を介してデータを送信する場合はencodeURIComponent()、特殊文字をエスケープする必要があります。

data: "stream="+encodeURIComponent(stream),
$json = json_decode(urldecode($json_str), true);

.live非難されている

この.live関数は 1.7 で廃止されました。この関数を使用して.onイベント ハンドラをアタッチする必要があります。あなたの場合、省略形 function を使用する方がよいでしょう.click()

リンクには href が必要です

<a>タグには href 属性が必要です。そうしないと、リンクにならず、使用し<div>ない場合は a を使用することになります。少なくとも. href="#"_event.preventDefault()

ファイル名

ファイルに名前を付けるときは、ピリオドを使用しないようにしてください。ピリオドstream.class.phpは発生するのを待っている事故です。一部のシステム (特に古いシステム) では、それらを適切に解釈できず、すべての名前を変更するのに苦労することになります。標準的な規則では、安定したファイル システムにはアンダースコアまたはハイフンを使用することをお勧めします。


これは私の側で機能します(すべてのファイルが同じフォルダーにあります)

HTML デフォルト (index.php)

<?php
    include_once("stream.php");
?>

<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    //load more posts
    $(document).ready(function(){
        $("#active").click(function(e) {
            e.preventDefault();

            var stream = '<?php echo $strm->encodeJSON();?>'; 
            var dataString = stream;
            var request = $.ajax({  
                type: "POST",  
                url: "loadmore.php",  
                data: "stream="+encodeURIComponent(stream),
                dataType: "html",
                beforeSend:function(data){
                    $('.load-more').html('<img src="ajax-loader(1).gif" alt="Loading..." />');
                },
                success: function(html) {
                    $('#active').remove();
                    $('#stream').append(html);
                }
            });

            //ajax error reporting
            request.fail(function(jqXHR, textStatus) {
                $('#active').html(textStatus);
            });
        });
    });
</script>
</head>

<body>
    <a href="#" class='load-more' id='active'>load more posts</a>
    <div id="stream"></div>
</body>
</html>

ストリーム.php

<?php

class Stream {
    private $limit;
    private $type;
    private $sort;
    private $offset=0;
    private $userID;
    private $catID;
    private $content = array();
    private $num_posts;

    function __construct(){
        $a = func_get_args();
        $i = func_num_args();
        if (method_exists($this,$f='__construct'.$i)) {
            call_user_func_array(array($this,$f),$a);
        }
    }

    function __construct5($limit, $type, $sort, $userID, $catID){
        $this->limit = $limit;
        $this->type = $type;
        $this->sort = $sort;
        $this->userID = $userID;
        $this->catID = $catID;
        //$this->num_posts = $this->retrieveTotal();

        //$this->setContent(); 
    }

    function __get($name) {
        if(isset($this->$name)){
            return $this->$name;
        }
    }

        public function encodeJSON(){
        foreach ($this as $key => $value){
            if($key != 'content'){
                $json->$key = $value;
            }
        }
        return json_encode($json);
    }

    public function decodeJSON($json_str){
        $json = json_decode(urldecode($json_str), true);

        foreach ($json as $key => $value){
            $this->$key = $value;
        }
    }
}

//create the object to be encoded
$strm = new Stream(5, 'toc', ' ', 1, ' ');

?>

loadmore.php

<?php

include_once('stream.php');

$strm = new Stream();

$strm->decodeJSON($_POST['stream']);

//Output a private property
echo $strm->__get("type");

?>
于 2012-04-04T08:33:40.737 に答える
1

多くの試行錯誤の後、私は問題を理解しました。Stream objectを使用する代わりに、エンコードされる をインスタンス化していたとき1$userID文字列としてキャストされ、URI エンコーディングをいじっていました。

stream=%7B%22limit%22%3A%225%22%2C%22type%22%3A%22toc%22%2C%22sort%22%3A%22%20%22%2C%22offset%22%3A%220%22%2C%22userID%22%3A%223%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%22%2C%22catID%22%3A%22%20%22%2C%22num_posts%22%3A%222%22%7D

なぜそのように振る舞うかはよくわかりませんが、解決策は $userID を整数としてキャストしています。それで:

$strm = new Stream(5, 'toc', ' ', (int)$userID, ' ');

URI エンコーディングは次のように変更されます。

stream=%7B%22limit%22%3A%225%22%2C%22type%22%3A%22toc%22%2C%22sort%22%3A%22%20%22%2C%22offset %22%3A%220%22%2C%22userID%22%3A%223%22%2C%22catID%22%3A%22%20%22%2C%22num_posts%22%3A%222%22%7D

および json_decode は配列を返します。

于 2012-04-04T14:12:26.273 に答える
0

JSON は、文字列に対して UTF-8 のみをサポートします。したがって、json_encode を実行する前に、すべての文字列を UTF-8 でエンコードする必要があります。ここで起こっているように見えるのは (あなたのすべてのコードを理解しているわけではありません)、「制御文字」のように json_encode に見える UTF8 のない文字列があることです。

于 2012-04-04T08:21:22.053 に答える