2

目标:

  1. json_encode具有私有属性的 PHP 对象
  2. 使用 jQuery通过低级 AJAX将编码对象作为数据字符串发送
  3. json_decode请求发送到的 AJAX URL 中的 PHP 对象

问题:

在第 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) 的 arg $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已弃用

自 1.7 起,该.live函数已弃用,您现在应该使用该函数.on附加事件处理程序。在你的情况下,你最好只使用速记函数.click()

链接必须有href

<a>标签必须有一个 href 属性,否则它不会是一个链接,<div>如果你不打算使用它,你还不如使用它。至少你应该有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, ' ');

?>

加载更多.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 对所有字符串进行编码。这里似乎发生的事情(我不明白你所有的代码)是你有一个没有 UTF8 的字符串,看起来像“控制字符”一样 json_encode。

于 2012-04-04T08:21:22.053 回答