navykoo
navykoo

Reputation: 47

JSON string (encoded from large array) got truncated when output to HTTP client

I met an issue that the JSON string output to HTTP client was truncated near to close tag.

An example,

a. expect to see - ... ... "last_update":"2014-06-10 20:46:38","garden_id":"1"}],"message":null}

b. actually it is - ... ..."last_update":"2014-06-10 20:46:38","garden_id":"1"}],"message":nul

The last two characaters were truncated for some reason!!!

I tried both Postman on Chrome and curl on a console, all the same output. So looks not a browser specific issue. The JSON string in my application comes from a PHP json_encode on an associative array. The PHP code is using CodeIgniter framework running on Apache. I tried to write the json string into a file before http output, the file content is 100% correct. So it is not a json encoding issue in PHP.

The PHP is pretty straightforward. I have build below array (namely $finaldata) from database query

{
    "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
}

the "data" has a sub array and it could be a long array depends on database records. Then the variable $finaldata is passed to a output function that has below general logic:

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

The output function is built by a RESTful library from https://github.com/philsturgeon/codeigniter-restserver. In this context, it equals to

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

But I found an interesting thing that the issue only happened if the string length exceeds 8K. And when I append a random string like "ZZZ" to the JSON string before HTTP response, the issue was gone. I don't know the reason behind. It is not a correct hack because I could not prove 8K is a real threshold though.

Has anyone met such issue before? Any suggestion or comments are appreciated.

Upvotes: 1

Views: 4748

Answers (2)

user7239338
user7239338

Reputation: 1

In my issue, I enable gzip in nginx,and append application/json to the field of gzip_types. Then, I set a header when make a request with Guzzle. It looks like

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

Upvotes: 0

TiMESPLiNTER
TiMESPLiNTER

Reputation: 5889

I think you send the data in UTF-8 charset so try to change this lines

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

into this one

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

If this doesn't work just don't send the Content-Length header at all. This header is "only useful" if you send a file to the browser (as a download).

Upvotes: 1

Related Questions