【问题标题】:JSON string (encoded from large array) got truncated when output to HTTP clientJSON 字符串(从大数组编码)在输出到 HTTP 客户端时被截断
【发布时间】:2014-08-10 00:55:33
【问题描述】:

我遇到了一个问题,即输出到 HTTP 客户端的 JSON 字符串在关闭标记附近被截断。

一个例子,

一个。期待看到 - ... ... "last_update":"2014-06-10 20:46:38","garden_id":"1"}],"message":null}

b.实际上是 - ... ..."last_update":"2014-06-10 20:46:38","garden_id":"1"}],"message":nul

最后两个字符由于某种原因被截断!!!

我在 Chrome 上尝试了 Postman,在控制台上尝试了 curl,所有输出都相同。所以看起来不是浏览器特定的问题。我的应用程序中的 JSON 字符串来自关联数组上的 PHP json_encode。 PHP 代码使用在 Apache 上运行的 CodeIgniter 框架。我尝试在 http 输出之前将 json 字符串写入文件,文件内容是 100% 正确的。所以这不是 PHP 中的 json 编码问题。

PHP 非常简单。我已经从数据库查询中构建了下面的数组(即 $finaldata)

{
    "success": true,
    "data": [
        {
            "file_id": "1",
            "title": "xxx",
            "create_date": "2014-05-18 21:30:19",
            "auditor": "1",
            "status": "1",
            "last_updater": null,
            "last_update": "2014-06-10 20:43:14",
            "garden_id": "1"
        },
        {
            "file_id": "2",
            "title": "yyy",
            "create_date": "2014-05-18 21:30:19",
            "auditor": "1",
            "status": "1",
            "last_updater": null,
            "last_update": "2014-06-10 20:43:14",
            "garden_id": "1"
        }
    ],
    "message": null
}

“数据”有一个子数组,它可能是一个长数组,取决于数据库记录。然后将变量 $finaldata 传递给具有以下一般逻辑的输出函数:

header('Content-Type: '.$this->_supported_formats[$this->response->format]);
$output = $this->format->factory($finaldata)->{'to_'.$this->response->format}();
header('Content-Length: ' . strlen($output));

输出函数由来自https://github.com/philsturgeon/codeigniter-restserver 的 RESTful 库构建。在这种情况下,它等于

header('Content-Type: Application/json');
$output = json_encode($finaldata);

但我发现了一个有趣的事情,即只有当字符串长度超过 8K 时才会出现问题。当我在 HTTP 响应之前将一个随机字符串(如“ZZZ”)附加到 JSON 字符串时,问题就消失了。我不知道背后的原因。这不是一个正确的 hack,因为我无法证明 8K 是一个真正的阈值。

有没有人遇到过这样的问题?任何建议或 cmets 表示赞赏。

【问题讨论】:

    标签: php json codeigniter


    【解决方案1】:

    在我的问题中,我在 nginx 中启用了 gzip,并将 application/json 附加到 gzip_types 的字段中。然后,我在向 Guzzle 发出请求时设置了一个标头。好像

        if (! isset($parameters['headers'])) {
            $parameters['headers']['Accept-Encoding'] = 'gzip';
        }
    

    【讨论】:

      【解决方案2】:

      我认为您以 UTF-8 字符集发送数据,因此请尝试更改此行

      header('Content-Type: '.$this->_supported_formats[$this->response->format]);
      header('Content-Length: ' . strlen($output));
      

      进入这个

      header('Content-Type: '.$this->_supported_formats[$this->response->format] . '; charset=utf-8');
      header('Content-Length: ' . mb_strlen($output));
      

      如果这不起作用,请根本不要发送 Content-Length 标头。如果您将文件发送到浏览器(作为下载),则此标头“仅有用”。

      【讨论】:

      • 刚试过,不行。我现在的技巧是 if(strlen($output)>8000){ $output = $output."ZZZ"; }
      • 尝试删除 Content-Length 标头语句并删除您的解决方法,看看字符串是否仍然被截断。
      • 哇,它似乎工作。它告诉我 strlen() 函数返回的大小不正确,对吧?
      • 可能是因为我的mbstring扩展没有配置好?现在在 php.ini 中这样配置 - [mbstring] mbstring.language = all mbstring.internal_encoding = UTF-8 mbstring.http_input = auto mbstring.http_output = UTF-8 mbstring.encoding_translation = On mbstring.detect_order = UTF-8 mbstring.substitute_character = 无; mbstring.func_overload = 0 mbstring.strict_encoding = Off
      • @navykoo 是的,strlen()mb_strlen() 似乎有问题。可以说您的 mbstring 现在是否配置正确。它是否适用于您在上面的评论中发布的设置?但如果它有效,则根本不要发送 Content-Length 标头。
      猜你喜欢
      • 2015-07-01
      • 1970-01-01
      • 2021-08-23
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多