json_encode() in PHP

之前看Yii2的源码的发现有这样一段代码

public static function encode($value, $options = 320)
{
	$expressions = [];
	$value = static::processData($value, $expressions, uniqid('', true));
	set_error_handler(function() {
		static::handleJsonError(JSON_ERROR_SYNTAX);
	}, E_WARNING);
	$json = json_encode($value, $options);
	restore_error_handler();
	static::handleJsonError(json_last_error());
	return $expressions === [] ? $json : strtr($json, $expressions);
}

为什么要设置set_error_handler呢?根据文档(http://php.net/manual/en/function.json-encode.php),encode失败时会返回FALSE,根本不会抛出异常。

查看git提交记录,https://github.com/yiisoft/yii2/commit/7bea7b65fdf21ae3e58339cc04376123416fcf81,发现这次提交的comment为“Improved JSON error handling to support PHP 5.5 error codes”,里面有说明

PHP 5.4 is throwing E_WARNING json_encode(): type is unsupported, encoded as null when you are trying to encode Resource
PHP 5.5 is result false with json_last_error() JSON_ERROR_UNSUPPORTED_TYPE
重现代码:

    $fp = fopen('php://stdin', 'r');
    var_dump(json_encode(['a' => $fp]));

JSON_ERROR_UNSUPPORTED_TYPE常量正好是在PHP 5.5.0加入的,而Yii2支持的PHP版本为 >= PHP 5.4 。