php - json_decode + ajax + 私有(private)属性 = 灾难 [错误 : JSON_ERROR_CTRL_CHAR]

标签 php jquery ajax json

目标:

  1. json_encode 具有私有(private)属性的 PHP 对象
  2. 通过 Low Level AJAX 将编码后的对象作为数据字符串发送使用 jQuery
  3. json_decode 请求发送到的 AJAX URL 中的 PHP 对象
  4. 获胜

问题:

在第 3 步中,json_last_error返回 3(JSON_ERROR_CTRL_CHAR 控制字符错误,可能编码不正确)

类(class):

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); 但什么也没有变化。

注意:建议我将类属性公开并不是解决方案

编辑:当我回显字符串时,{ “限制”:“5”, “类型”:“目录”, “种类”: ” ”, “偏移”:“0”, “用户ID”:“3”, “猫ID”:“”, “帖子数量”:“2” } 被发送到decodeJSON,它测试为 valid

此屏幕截图显示了发送到decodeJSON($json_str) 的参数$json_str 和错误代码。 json_str param and error

最佳答案

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(); ?>';

它应该可以正常工作。

其他

encodeURIComponent

一般来说,通过 AJAX 发送数据时,您应该 encodeURIComponent() 它可以转义任何特殊字符。

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

<强> .live已弃用

.live 函数从 1.7 开始已弃用,您现在应该使用函数 .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, ' ');

?>

loadmore.php

<?php

include_once('stream.php');

$strm = new Stream();

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

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

?>

关于php - json_decode + ajax + 私有(private)属性 = 灾难 [错误 : JSON_ERROR_CTRL_CHAR],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10005796/

相关文章:

php - SELECT 查询中的 MySQL 语法错误

phpredis 跟 Redis 走

php - 使用 POST 方法从 javascript 向服务器发送 json 数据的问题

jquery - 菜单末尾的 Typeahead.js 页脚文本

javascript - 使用 AJAX 和 PHP 登录时获取用户配置文件

javascript - 多文件上传,onchange-action 未触发

jquery - 带有 jQ​​uery 的 CSS 下拉菜单

php - Ajax 方法显示错误的输入

javascript - Ajax 搜索和分页相结合

javascript - PHP 错误 - 仅以文本格式显示代码