[FEATURE]修改kotlin扩展Any.contains函数名,以及其他类似的相关扩展函数 · Issue #1402 · alibaba/fastjson2 · GitHub

您所在的位置:网站首页 signed函数 [FEATURE]修改kotlin扩展Any.contains函数名,以及其他类似的相关扩展函数 · Issue #1402 · alibaba/fastjson2 · GitHub

[FEATURE]修改kotlin扩展Any.contains函数名,以及其他类似的相关扩展函数 · Issue #1402 · alibaba/fastjson2 · GitHub

2023-04-26 06:13| 来源: 网络整理| 查看: 265

问题和需求描述

在一次debug过程中,我们团队发现一句必定正确的逻辑判断永远返回false,最终我们发现是fastjson2间接引起的问题.

1.起因

fastjson2的kotlin扩展包为kotlin提供了许多扩展方法,如parseArray()、parseObject()、to()、into()、eval()等,去年我们使用kotlin + springboot的项目将fastjson包升级到了2.0,升级的原因之一就是新版提供了kotlin支持,同时,我们引入kotlin扩展包的初期体验到了极大的方便:

新的api和kotlin代码风格融合,在dsl语法的使用中简化了代码,提高了可读性。 但是,这些扩展函数的设计中,有少数几个扩展函数存在很大的问题。

拿我最开始的情况,举个例子:

kotlin.text包内String的contains函数是一个非常常用的函数,用于判断字符串的包含关系 自从2.0.4以来,fastjson2提供了一个没有限制作用域和类型的扩展函数Any.contains

@Suppress( "HasPlatformType", "NOTHING_TO_INLINE" ) inline fun Any.contains( path: String ) = JSONPath.of(path).contains(this)

这个扩展函数经常会在调用String.contains(other)的时候被悄悄自动引入进来,导致一些非常隐含的报错,而且一旦引入,整个文件所有的contains都完了。 如下图所示,它的优先级甚至比kotlin.text默认的contains(charSequence)还高。 截屏2023-04-24 11 05 47

作为一个写kotlin各种平台(android/后台/multiplatform)代码,并且设计过kotlin框架的人,我认为这些函数存在以下问题:

这些扩展函数没有作用域,他们在项目的任何地方都可以调用,而不是在某些特定的类内 这些函数为了达到使用简单,和系统提供的很多常用的函数重名,如contains,to(kotlin使用to作为二维元组的连接中缀,相当于JS里面的“:”,不过好在一般会使用"foo" to "bar",很少会使用"foo".to("bar"))等,函数名和参数里也没有体现出和JSON有关的任何标识 这些扩展函数的使用对象为Any,如contains,eval,writeTo等,很多类可能有自己的contains、eval、writeTo函数,在调用时很可能会调错 请描述你建议的实现方案 修改函数名 像Any.toJSONString这种就不会引起歧义,可以考虑修改函数名 需要做的就是将有关的函数设置为废弃,修改函数名后重新发包(可以使用@deprecated + ReplaceWith) @Deprecated( "The 'function xxx' xxx will be removed soon, please use xxxxx", ReplaceWith("xxx.xxx(xxx)", "xxxx") ) fun xxx

我认为contains这个函数修改的优先级很高,其他名字中没有体现JSON的、加在Any上的扩展函数是一种很不负责任的起名方式,毕竟扩展函数会对整个项目所有的对象函数调用进行污染。

另一种解决方法,增加RequiresOptIn 增加一个@RequiresOptIn(level = RequiresOptIn.Level.ERROR, message = "xxx")注解,在调用此类函数时需要额外加入一个Opt,及早发现调用了错误的函数,防止这一类bug的发生。 例: @RequiresOptIn(level = RequiresOptIn.Level.ERROR, message = "This is a function applied by fastjson2, please notice!") @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class FastJsonForKotlin @Suppress( "HasPlatformType", "NOTHING_TO_INLINE" ) @FastJsonForKotlin inline fun Any.contains( path: String ) = JSONPath.of(path).contains(this)

实际调用时: 截屏2023-04-24 12 04 57



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3