新一代Json解析库Moshi使用及原理解析 ,美团架构师深入讲解Android开发

@Serializable
data class Chinese(@Optional val age: Int = 0, @Optional val country: String? = “China”) {
@Optional
private val hobby: String = “travel”
}

fun main(args: Array) {
val gsonBean = Gson().fromJson(“”“{“age”:4}”“”, Chinese::class.javaObjectType)
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val adapter = moshi.adapter(Chinese::class.java)
val moshiBean = adapter.fromJson(“”“{“age”:4}”“”)
val kxBean = JSON.parse(Chinese.serializer(), “”“{“age”:4}”“”)

}

我们解析上述数据,发现Gson解析到的gsonBean对象中的country及hobby这两个字段都是null,但是Moshi跟KX反序列化后的对象country跟hobby都是我们给予的默认值,这个问题Gson在解析Java的时候是没有的,但是在Kotlin中就失效了。原因可以从Gson的源码中得到答案,在采用反射解析的时候,Gson构造对象实例时调用的是默认无参构造方法,所以没有默认值也就不足为奇了。那么hobby为什么也没有,因为在Gson并不知道什么是数据类,所以他依然不认识hobby。

空安全

在Java中,我们可以用注解@Nullable和NotNull来标记一个变量或者方法参数是否可空,但是加注解比较麻烦,所以我们很多时候都不会去加注解,一般都是在使用的时候进行非空判断,所以Java代码在调用解析后的Bean对象的时候都需要进行非空判断,Kotlin在这种情况下进行了完善,可以在定义的时候指定对象是否可空,这样在使用非空对象的时候就无需进行判断了,但是如果针对一个方法的参数是非空的,你传入了一个空值,编译就会报错,那么同样的道理,如果我们在定义Data类的时候,如果指定了一个字段为非空类型,那么如果Json数据里面这个字段为Null就应该报错,下面看看三个框架的实现逻辑

@Serializable
data class Chinese(@Optional val age: Int = 0, @Optional val country: String? = “China”) {
@Optional
private val hobby: String = “travel”
}
fun main(args: Array) {
val gsonBean = Gson().fromJson(“”“{“age”:null}”“”, Chinese::class.javaObjectType)
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val adapter = moshi.adapter(Chinese::class.java)
val moshiBean = adapter.fromJson(“”“{“age”:null}”“”)
val kxBean = JSON.parse(Chinese.serializer(), “”“{“age”:null}”“”)
}

测试的时候发现Moshi跟KS都报错了,但是Gson是正常的,按照Kotlin的语法这个是不合理的,我们是需要报错的,因为age字段是不可空的,而这里却传了一个空参数,所以Gson在这里的处理是有问题的。原因我们之前说过,虽然Kotlin最终被编译成的字节码也是运行在JVM上的,但是Gson反射的时候无法区分Java跟Kotlin,所以还是按照Java的解析规则去解析的,因为Json的key为Null在Java中是正常的,即使这在Kotlin中已经无法执行。

结论

针对上面的测试,下面根据项目的实际使用情况总结一下

  • 混编项目:使用Moshi,兼顾Java跟Kotlin

  • Java项目:建议使用Gson,如果反序列化需求比较多,建议使用Moshi,因为它内置Okio

  • Kotlin项目:跨平台的话,使用KS;非跨平台,如果仅仅是反序列化,Moshi跟KS均可,如果序列化较多,使用Moshi

基本用法之Java

Dependency

implementation ‘com.squareup.moshi:moshi:1.8.0’

Bean

String json = …;
Moshi moshi = new Moshi.Builder().build();
JsonAdapter jsonAdapter = moshi.adapter(Bean.class);
//Deserialize
Bean bean = jsonAdapter.fromJson(json);
//Serialize
String json = jsonAdapter.toJson(bean);

List

Moshi moshi = new Moshi.Builder().build();
Type listOfCardsType = Types.newParameterizedType(List.class, Bean.class);
JsonAdapter<List> jsonAdapter = moshi.adapter(listOfCardsType);
//Deserialize
List beans = jsonAdapter.fromJson(json);
//Serialize
String json = jsonAdapter.fromJson(json);

Map

Moshi moshi = new Moshi.Builder().build();
ParameterizedType newMapType = Types.newParameterizedType(Map.class, String.class, Integer.class);
JsonAd

  • 16
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值