
Moshi Vs Gson Vs Kotlin Serialisation
定义
- Gson
 
Gson 是一个Java序列化/反序列化库,用于将Java对象转换为JSON格式,以及将JSON格式转换回Java对象。
- Moshi
 
Moshi 是一个现代化的JSON库,适用于Android和Java。它使得将JSON解析为Java对象以及将Java对象转换回JSON变得简单。
- Kotlin序列化
 
Kotlin序列化是一种以Kotlin为主导的、在编译时类型安全、无反射且完全跨平台准备的序列化机制,用于将Kotlin对象转换为JSON或Protobuf等数据格式,反之亦然。该库不使用无反射,而是采用显式注解 @Serializable。应用该注解后,编译器插件会在伴生对象上添加一个特殊的函数 serializer(),返回类型为 KSerializer 的序列化器。KSerializer 对象实现了所需的接口,用于序列化和反序列化数据类。
性能比较
为了定义比较,创建了一个基准测试规则,可以总结如下代码片段:
class SerializableBenchMark {
    lateinit var json: Json
    lateinit var moshi: Moshi
    lateinit var gson: Gson
    lateinit var response: String
    private val context = InstrumentationRegistry.getInstrumentation().targetContext
    @Before
    fun setup() {
        json = Json {
            ignoreUnknownKeys = true
            isLenient = true
            encodeDefaults = false
            coerceInputValues = true
        }
        moshi = Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()
        gson = GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
            .setLenient().create()
        response = context.assets.open("sample_response.json").use {
            it.bufferedReader().readText()
        }
    }
    @get:Rule
    val benchmarkRule = BenchmarkRule()
    @Test
    fun exampleKotlinSerialisation() = benchmarkRule.measureRepeated {
        json.decodeFromString(Response.serializer(), response)
    }
    @Test
    fun exampleMoshi() = benchmarkRule.measureRepeated {
        val jsonAdapter = moshi.adapter(Response::class.java)
        jsonAdapter.fromJson(response)
    }
    @Test
    fun exampleGson() = benchmarkRule.measureRepeated {
          gson.fromJson(response, Response.javaClass)
    }
}
 
- 这里的 
sample_response.json是从此链接构建的。 
https://www.covidvisualizer.com/api
结果
测试用例 1 — 基准测试
我已记录了每个测试用例对应的 benchmark-data.json 文件,以便进行比较。
设备详情
"build": {
            "brand": "vivo",
            "device": "2130",
            "fingerprint": "vivo/2130i/2130:12/SP1A.210812.003/compiler05210733:user/release-keys",
            "model": "V2130",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": true,
        "cpuMaxFreqHz": 2500000000,
        "memTotalBytes": 12146495488,
        "sustainedPerformanceModeEnabled": false
    }
 
Kotlin -Serialisation
"benchmarks": [
        {
            "name": "PROFILED_exampleKotlinSerialisation",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 12119030155,
            "metrics": {
                "timeNs": {
                    "minimum": 3.802098385E9,
                    "maximum": 3.802098385E9,
                    "median": 3.802098385E9,
                    "runs": [
                        3.802098385E9
                    ]
                },
                "allocationCount": {
                    "minimum": 19390.0,
                    "maximum": 19390.0,
                    "median": 19390.0,
                    "runs": [
                        19390.0,
                        19390.0,
                        19390.0,
                        19390.0,
                        19390.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 2310,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]
 
Moshi
"benchmarks": [
        {
            "name": "PROFILED_exampleMoshi",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 11961625309,
            "metrics": {
                "timeNs": {
                    "minimum": 3.531992307E9,
                    "maximum": 3.531992307E9,
                    "median": 3.531992307E9,
                    "runs": [
                        3.531992307E9
                    ]
                },
                "allocationCount": {
                    "minimum": 14509.0,
                    "maximum": 16854.0,
                    "median": 14509.0,
                    "runs": [
                        16854.0,
                        14509.0,
                        14509.0,
                        14509.0,
                        14509.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 1202,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]
 
Gson
"benchmarks": [
        {
            "name": "PROFILED_exampleGson",
            "params": {},
            "className": "com.example.benchmark.SerializableBenchMark",
            "totalRunTimeNs": 1331248385,
            "metrics": {
                "timeNs": {
                    "minimum": 1.76971077E8,
                    "maximum": 1.76971077E8,
                    "median": 1.76971077E8,
                    "runs": [
                        1.76971077E8
                    ]
                },
                "allocationCount": {
                    "minimum": 20.0,
                    "maximum": 20.0,
                    "median": 20.0,
                    "runs": [
                        20.0,
                        20.0,
                        20.0,
                        20.0,
                        20.0
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 1062,
            "repeatIterations": 1,
            "thermalThrottleSleepSeconds": 0
        }
    ]
 
从上面的结果可以看出,Kotlin-serialisation 花费了 12.11 秒,Moshi 花费了 11.96 秒,而 Gson 花费了 13.31 秒。
测试用例 2 — 字段不存在
在这里,我从 US 节点中移除了 name 节点,如下截图所示。
 
 Kotlin-Serialisation测试截图如下
 
 Moshi测试截图如下
 
 在这种情况下,Gson 忽略了该字段并完全执行了。
对于所有这些,我们可以看到 Moshi 的错误相对于其他两者来说更具体。
测试用例 3 - 使用基准报告
单次迭代结果
 
 5次迭代结果
 
结论
总体而言,在序列化/反序列化方面,Moshi 显示出了良好的结果,但 Kotlin 序列化具有 Protobuf 支持,可以帮助降低延迟和有效载荷大小,因此根据用途,人们可以谨慎选择所需的库。



















