摘要
今天在开发的时候遇到了一个奇葩问题,记录一下,防止以后遇到,也让一些遇到的小伙伴有点思路;
使用的第三方包
用了FastJson作为Json解析工具,网络三件套
ps:感觉涉及到序列话都会有问题
情景
原有的项目是用Java写的,近期在修改部分文件转为Kotlin,不得不说,kotlin的data class是真的香,至少目前很香,虽说遇到了很多坑,当然不是本文的重点,就不谈了。
好了,继续说,我有一个data class的实体类,
例如:我有一个类,Student
。
// 一个Kotlin 版本的 Student诞生了
@Parcelize
data class Student(var name: String? = null,
var isLocal: Boolean? = false,//类型::Boolean,is开头,getter方法‘重写为’ getIs...
var isBoy: Boolean? = false,//类型::Boolean, is开头,getter方法默认生成 is...
var isFoolish: Int? = -1,//类型::Int,is开头,getter方法‘重写为’ getIs...
var isLike: String? = null//类型::String,is开头,getter方法默认生成 is...
) : Parcelable {
fun getIsLocal(): Boolean? {
return isLocal
}
fun getIsFoolish(): Int? {
return isFoolish
}
}
重点关注is
开头的几个属性,和对应的Getter
方法,接下来我们进行序列化和反序列化,其实就是用创建个对象,用Fastjson进行解析转化为文本,如下:
class Test {
//输入co 回车
companion object {
//输入maino 回车就出现mian方法了,慎用,容易上瘾
@JvmStatic
fun main(args: Array<String>) {
val student = Student()
student.name = "张三" //永远的张三
student.isLocal = true
student.isBoy = false
student.isFoolish = 1
student.isLike = "跳皮筋"
val jsonStr = JSONObject.toJSONString(student)
println("实体转JsonString后::$jsonStr")
val json = JSONObject.parse(jsonStr)
println("将Json字符串转化为JSON$json.toString()")
val newStudent = JSONObject.parseObject(jsonStr, Student::class.java)
println("将Json字符串转化为实体类$newStudent.toString()")
println("列举反射成员属性和方法::")
newStudent::class.members.forEach { println(it.toString()) }
}
}
}
打印结果:
实体转JsonString后::{ "boy":false, "isFoolish":1, "isLocal":true, "local":true, "name":"张三" }
将Json字符串转化为JSON{ "name":"张三", "isFoolish":1, "boy":false, "local":true, "isLocal":true }.toString()
将Json字符串转化为实体类Student(name=张三, isLocal=true, isBoy=false, isFoolish=1, isLike=null).toString()
枚举反射成员属性和方法::
var Student.isBoy: kotlin.Boolean?
var Student.isFoolish: kotlin.Int?
var Student.isLike: kotlin.String?
var Student.isLocal: kotlin.Boolean?
...
fun Student.getIsFoolish(): kotlin.Int?
fun Student.getIsLocal(): kotlin.Boolean?
序列化后导致以下情况:
- 不管是否Boolean类型,用data class自动生成的
is...
方法消失了 - 不管是否Boolean类型,通过反编码为Java后,is开头字段的getter方法会变为is…方法
- 不管是否Boolean类型,手动“重写”的getter则会不会消失,能通过反射获取
- 不管是否Boolean类型,手动“重写”的getter方法也是正常显示
差点重装Android Studio
因上次遇到过一次Android studio 的缓存问题,在序列化接口入参的时候一直获取不到某个值,甚至一度认为是Android Studio出的问题,哈哈哈哈,结果不是,真尴尬。
解决方案
经过研究测试,总结了三种方案:
让后台修改字段名,不用这个了(就是这么霸气,你要么别问我要,问我要就必须按我的来),不推荐- 上面代码也看到了,手动重写getter,详见上述代码
- 本地修改字段名成,并且设置Json序列化的命名,如下修改实体类:
// 一个Kotlin 版本的 Student诞生了
@Parcelize
data class Student(var name: String? = null,
@JSONField(name="isLocal")
var abc: Boolean? = false,//类型::Boolean,is开头,getter方法‘重写为’ getIs...
@JSONField(name="isLocal")
var boy1213: Boolean? = false,//类型::Boolean, is开头,getter方法默认生成 is...
@JSONField(name="isLocal")
var foolishAAAA: Int? = -1,//类型::Int,is开头,getter方法‘重写为’ getIs...
@JSONField(name="isLocal")
var likeAbc: String? = null//类型::String,is开头,getter方法默认生成 is...
) : Parcelable
名字可以随便去,最终序列化后的名字就是name
后面所对应的值。
总结
第一次正儿八经写博客,还有待研究学习和提升,下回有问题见。
大佬给点赞鼓鼓力。