1

I am using a PHP 5.6.40 development environment. Many of my classes implement JsonSerializable. The jsonSerialize method of one of these classes uses json_decode, since the value of one of its data members may or may not be encoded as JSON. The problem is that after calling json_decode on a data member whose value is just a plain string, the json_encode fails.

Here is an example:

class JsonSerializableClass implements JsonSerializable
{
    private $dataMember;

    public function __construct($dataMember)
    {
        $this->dataMember = $dataMember;
    }

    public function jsonSerialize()
    {
        $decodedDataMember = json_decode($this->dataMember, 1);

        if ($decodedDataMember && $decodedDataMember['jsonDataMember'])
        {
            return $decodedDataMember['jsonDataMember'];
        }

        // json_encode(''); This keeps json_encode from failing, but I'm looking for a different solution.

        return $this->dataMember;
    }
}

// This works
$test1 = new JsonSerializableClass(json_encode(array(
        'jsonDataMember' => 'plain string'
)));
var_export(json_encode($test1));

// This fails
$test2 = new JsonSerializableClass('plain string');
var_export(json_encode($test2));

This is fixed by adding a call to json_encode in the jsonSerialize method after the failed json_decode; however, another developer may not immediately realize what that accomplishes. Of course I would comment my reasoning for doing it, but I'm looking for a more clear solution. Is there error state data that json functions rely on that is being cleared by a successful json_encode? If so, is there a way to clearly reset that error state data, like clear_json_error_state?

I'm sorry if my explanation is hard to understand; it was difficult for me to explain. Please ask me for any clarification you need.

hutch90
  • 341
  • 3
  • 15
  • why not do a try, catch inside your function with json_encode? why rely on json_encode outside the function? return a string regardless of your input. You can also add checks for types if you are not sure that it will always be a string and/or json – Dan Jan 25 '20 at 00:39
  • A failed ```json_decode``` does not throw an error; it returns false. The last error can be retrieved using ```json_last_error``` and the message can be retrieved using ```json_last_error_msg```. The outer ```json_encode``` is encoding a lot of data, not just one of these records. The value being passed to ```json_decode``` is always a string. I just don't know if it's valid json until after putting it through ```json_decode```. – hutch90 Jan 25 '20 at 00:47
  • What error state are you referring to? I tried your script, it echoed `"plain string"` twice. But this was in PHP 7, is it different in PHP 5? – Barmar Jan 25 '20 at 00:56
  • @Barmar Yes. My development machine uses PHP 7.3.9. This code works just fine in that environment. The production environment uses PHP 5.6.40, where this code fails. The second ```echo``` may not print anything visible on the screen. If I were to use ```var_export``` instead, then it should display ```NULL```. I will update the description. – hutch90 Jan 25 '20 at 00:59
  • I think this is just a bug in PHP, and it was fixed in PHP 7. I don't think there's any direct access to whatever state is causing it, and your workaround seems fine. I would use `if (php_last_error())` to check whether `json_decode()` got an error. – Barmar Jan 25 '20 at 01:09
  • That's what I'm afraid of. It's not the end of the world if I have to use json_encode, but it would be nice if there was some other way. – hutch90 Jan 25 '20 at 01:14

1 Answers1

-1

I downgrade the version to V4.1.5, It works.

"name": "pusher/pusher-php-server", "version": "v4.1.5",

codeCraft
  • 62
  • 5