Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Optimized code for Hyperf\Codec\Exception\InvalidArgumentException which you can be used to get the original data. #6218

Open
wants to merge 20 commits into
base: 3.0
Choose a base branch
from

Conversation

greezen
Copy link
Contributor

@greezen greezen commented Oct 16, 2023

问题场景:json_encode 的内容有不完整的 utf8 字符时,会导致编码错误。异常中没有具体的数据信息,不方便排查。
添加:设置/获取原始数据的功能
使用方法:

try {
            $originData = '高性能、高灵活性的渐进式 PHP 协程框架';
            Json::encode(substr($originData, 0, 8));
        } catch (JsonInvalidArgumentException $th) {
            var_dump(json_encode($th->getOriginData(), JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE));
        }

添加以上方法后,工程师可以根据自己的情况记录日志,方便快速定位问题

src/codec/src/Json.php Outdated Show resolved Hide resolved
@limingxinleo limingxinleo changed the title refactor: add set/get json origin data Use InvalidJsonException instead of InvalidArgumentException when Json::encode or Json::decode failed Oct 16, 2023
@limingxinleo limingxinleo changed the title Use InvalidJsonException instead of InvalidArgumentException when Json::encode or Json::decode failed Optimized code for Hyperf\Codec\Exception\InvalidArgumentException which you can be used to get the origin data. Oct 16, 2023
@limingxinleo
Copy link
Member

我们内部讨论了下,这个还是用户自己处理吧。

既然都抛出异常了,正常情况下肯定是预先考虑到了,那 try catch 里处理的时候,根本没必要从 exception 里拿数据,直接从上下文拿就可以了。

@greezen
Copy link
Contributor Author

greezen commented Oct 16, 2023

如果是在常规的业务代码中是比较好处理,若在 respone 时报错,貌似没有更好的方式,比如从数据库查出来就是乱码的,可能要排查好几个字段才能查到(多张表得到的结果)

@limingxinleo
Copy link
Member

try {
            $originData = '高性能、高灵活性的渐进式 PHP 协程框架';
            Json::encode(substr($originData, 0, 8));
        } catch (JsonInvalidArgumentException $th) {
            var_dump(json_encode($originData, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE));
        }

这样用岂不是也很简单

@limingxinleo
Copy link
Member

描述一个例子吧,现在确实无法说服我们大多数人合并这个 pr

@huangdijia
Copy link
Member

AOP 处理也可以

@greezen
Copy link
Contributor Author

greezen commented Oct 16, 2023

描述一个例子吧,现在确实无法说服我们大多数人合并这个 pr

场景描述:商品详情页有 50 个相关字段,用户打开某一商品时,由于乱码导致返回 json 时 500 错误,异常信息中没有相关的数据信息,排查时只能靠人眼扫描,效率很低。如果能自定义 json 的参数也能比较友好的解决这个问题,如:
$this->response->json($data,JSON_xxx)

@limingxinleo
Copy link
Member

好吧,现在这个情况,确实可以你自己处理下就能解决的

image

如果你使用的官方 json 方法,肯定会走到上面的方法,所以你实际上自己在外层 try catch 如果有问题,直接可以拿到 上面的 data 而非从 异常里来拿了。

$this->response->json($data,JSON_xxx)

当然,正常情况下,你肯定这个方法要进行封装的,类似这里

https://github.com/hyperf/biz-skeleton/blob/master/app/Kernel/Http/Response.php#L34

只需要这里处理一下就行了。

@greezen
Copy link
Contributor Author

greezen commented Oct 16, 2023

好吧,现在这个情况,确实可以你自己处理下就能解决的

image

如果你使用的官方 json 方法,肯定会走到上面的方法,所以你实际上自己在外层 try catch 如果有问题,直接可以拿到 上面的 data 而非从 异常里来拿了。

$this->response->json($data,JSON_xxx)

当然,正常情况下,你肯定这个方法要进行封装的,类似这里

https://github.com/hyperf/biz-skeleton/blob/master/app/Kernel/Http/Response.php#L34

只需要这里处理一下就行了。

好的,我试试,谢大佬

@limingxinleo
Copy link
Member

这个 pr 不用关,先放着,是个后来可期的功能,但是暂时有点鸡肋

@greezen
Copy link
Contributor Author

greezen commented Oct 17, 2023

以下是 laravle 中的写法,感觉支持传参是比较好的方式

return response()->json(['status' => 1, 'msg' => substr('我是高性能、高灵活性的渐进式 PHP 协程框架',0, 4)], 200,[],JSON_INVALID_UTF8_SUBSTITUTE);

@limingxinleo
Copy link
Member

要学会变通啊。。

    public function json($data): PsrResponseInterface
    {
        $data = $this->toJson($data);
        return $this->getResponse()
            ->addHeader('content-type', 'application/json; charset=utf-8')
            ->setBody(new SwooleStream($data));
    }

你大可以封装一个方法来用啊,不一定非要用官方封装的

@greezen
Copy link
Contributor Author

greezen commented Oct 17, 2023

要学会变通啊。。

    public function json($data): PsrResponseInterface
    {
        $data = $this->toJson($data);
        return $this->getResponse()
            ->addHeader('content-type', 'application/json; charset=utf-8')
            ->setBody(new SwooleStream($data));
    }

你大可以封装一个方法来用啊,不一定非要用官方封装的

是可以,但感觉是在重复造轮子,哈哈哈

@limingxinleo
Copy link
Member

不重复,Hyperf 主打的就是灵活高效高性能,这符合框架的设计理念。

huangdijia
huangdijia previously approved these changes Oct 19, 2023
@huangdijia huangdijia changed the base branch from master to 3.0 December 5, 2023 09:36
@huangdijia huangdijia dismissed their stale review December 5, 2023 09:36

The base branch was changed.

@huangdijia huangdijia changed the title Optimized code for Hyperf\Codec\Exception\InvalidArgumentException which you can be used to get the origin data. Optimized code for Hyperf\Codec\Exception\InvalidArgumentException which you can be used to get the original data. Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants