Skip to content

ErrorException: json_decode(): option JSON_BIGINT_AS_STRING not implemented #28

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
micahaza opened this issue Apr 26, 2016 · 19 comments
Closed
Milestone

Comments

@micahaza
Copy link

I try to consume my own Laravel 5 API JSON response and I got this error message:

ErrorException: json_decode(): option JSON_BIGINT_AS_STRING not implemented

For this JSON output:

{
"errors": [
{
"status": "404",
"source": {
"pointer": "http://localhost/api/v1/this-is-not-exist-for-sure"
},
"title": "The requested resource has not been found",
"detail": "We're sorry, something unthinkable happened"
}
]
}

Did I do anything wrong?

/**
 * @test
 */
public function it_proves_we_will_get_proper_json_for_404()
{
     $this->json('GET', 'api/v1/this-is-not-exist-for-sure', $this->validHttpHeader)
        ->seeStatusCode(404)
        ->seeJsonContains(['status' => "404"]);
    $resp = json_decode($this->response->content());
    $manager = new Manager();
    $exception = $manager->parse((string)$this->response->content());
}
@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

This seems to be a bug in PHP 5.5 with the php-json package on Ubuntu, see https://stackoverflow.com/questions/19520487/json-bigint-as-string-removed-in-php-5-5

I'm investigating if I can reproduce and create a workaround for this issue.

@micahaza
Copy link
Author

micahaza commented Apr 26, 2016

I can send you a test implementation if you'd like it. Let me know if you need any help.
I'm using
PHP 5.5.9-1ubuntu4.16 (cli) (built: Apr 20 2016 14:31:27)

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

That would be nice.

Or can you test, if this workaround works for you?

$input = '{"errors": []}';

if (version_compare(PHP_VERSION, '5.4.0', '>=') && ! (defined('JSON_C_VERSION') && PHP_INT_SIZE > 4))
{
    $obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
}
else
{
    $max_int_length = strlen((string) PHP_INT_MAX) - 1;
    $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
    $obj = json_decode($json_without_bigints);
}

@micahaza
Copy link
Author

The problem is I don't want to use json_decode() directly, I just want to use your package. This workaround works if and only if I want to json_decode() directly if I'm not mistaken.

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

I understand. I just wanted to ensure that this workaround works for your issue, so I can put it in the package.

@Art4 Art4 added this to the 0.6.3 milestone Apr 26, 2016
@micahaza
Copy link
Author

micahaza commented Apr 26, 2016

This workaround will work for me if I you'd encapsulate all your json_decode() calls.
It looks like this is only occurs once:
src/Utils/DataContainer.php: return json_decode(json_encode($val), true);
And in tests also.

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

Great. This is no problem. A fix is on the way.

@micahaza
Copy link
Author

Sounds good. Let me know if I can test it.

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

There is a bug in the workaround. It cannot handle this situation:

$json_string = '
{
    "fake_int": ":1234567890123",
    "real_int": 1234567890123
}';

So, another workaround would be to only use JSON_BIGINT_AS_STRING if it is supported. Can you please test this workaround?

$json_string = '
{
    "fake_int": ":1234567890123",
    "real_int": 1234567890123
}';

$options = ( version_compare(PHP_VERSION, '5.4.0', '>=') and ! (defined('JSON_C_VERSION') and PHP_INT_SIZE > 4) ) ? JSON_BIGINT_AS_STRING : 0;
$data = json_decode($json_string, false, 512, $options);

var_dump($data);

@micahaza
Copy link
Author

micahaza commented Apr 26, 2016

It returns me this:

object(stdClass)#29 (2) {
  ["fake_int"]=>
  string(14) ":1234567890123"
  ["real_int"]=>
  int(1234567890123)
}

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

Great. But now I have discovered an issue on my Ubuntu machine which don't parse big integers into strings correctly. 😄 Could you please test the parsing of this big integer

$json_string = '{"big_int": 123456789012345678901234567890}';

$options = ( version_compare(PHP_VERSION, '5.4.0', '>=') and ! (defined('JSON_C_VERSION') and PHP_INT_SIZE > 4) ) ? JSON_BIGINT_AS_STRING : 0;
$data = json_decode($json_string, false, 512, $options);

var_dump($data, defined('JSON_C_VERSION'), PHP_INT_SIZE, $options);

and give me some information about your CPU (32 or 64 bit) and your PHP version, please?

uname -a
php -v

@micahaza
Copy link
Author

pezo@pezo-pc:/tmp$ uname -a
Linux pezo-pc 3.19.0-58-generic #64~14.04.1-Ubuntu SMP Fri Mar 18 19:05:43 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
pezo@pezo-pc:/tmp$ php -v
PHP 5.5.9-1ubuntu4.16 (cli) (built: Apr 20 2016 14:31:27) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
pezo@pezo-pc:/tmp$ 

output of your big integer parsing:

object(stdClass)#29 (1) {
  ["big_int"]=>
  int(9223372036854775807)
}
bool(true)
int(8)
int(0)

@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

Thank you. I have the same (wrong) integer result on my Ubuntu machine and I think this is a bug that JsonApiClient can't fix.

I will add the workaround:

$options = ( version_compare(PHP_VERSION, '5.4.0', '>=') and ! (defined('JSON_C_VERSION') and PHP_INT_SIZE > 4) ) ? JSON_BIGINT_AS_STRING : 0;
$data = json_decode($json_string, false, 512, $options);

But you have to keep in mind that integers bigger than 9223372036854775807 would be interpreted wrong by json_decode. If you expect big integers you have to prepare the JSON string before giving it to $manager->parse().

@Art4 Art4 closed this as completed in 4579f73 Apr 26, 2016
@Art4
Copy link
Owner

Art4 commented Apr 26, 2016

I just released 0.6.3

@micahaza
Copy link
Author

Thank you. Other question. What do you think, which library/PHP module do I need to replace/upgrade in order to get rid of this issue?

@Art4
Copy link
Owner

Art4 commented Apr 27, 2016

Afaik you have two choices:

  1. Update jsonc to >= 1.3.8, where the issue was fixed
  2. Update to PHP 7 which uses jsond (see the rfc)

@micahaza
Copy link
Author

micahaza commented Apr 27, 2016

root# pecl install jsonc
downloading jsonc-1.3.9.tgz ...

solved the problem. Many thanks for your time.

bash$ php -i | grep -i json
json support => enabled
json version => 1.3.9
JSON-C version (bundled) => 0.11

@Art4
Copy link
Owner

Art4 commented Apr 27, 2016

I'm glad I could help.

@micahaza
Copy link
Author

Thank you again, let me know if you need any help. I owe you one. 👍

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

2 participants