换了Solon框架后 all in kt 遇到了一个问题。就是json数据层级深的时候只能序列化第一层,经过测试主流的json框架都是这样。
研究了一天终于找到一个不依赖的解决方法。先上结果代码:
@OptIn(ExperimentalStdlibApi::class)
fun main(args: Array<String>) {
val ret = """{"code":200,"msg":"成功","data":{"id":"out123","name":"outName","inner":{"id":"inner123","name":"innerName","innerdata":["1","2","3"]}}}"""
// inner解析结果 snack3: false | fastJson2: false | gson: false
val snack3 = ONode.deserialize<Ret<Out>>(ret,Ret<Out>()::class.java)
val fastJson2 = JSON.parseObject<Ret<Out>>(ret, Ret<Out>()::class.java)
val gson = Gson().fromJson<Ret<Out>>(ret, Ret<Out>()::class.java)
// inner解析结果 snack3: true | fastJson2: true | gson: true
val typeOf_T = typeOf<Ret<Out>>().javaType
val typeOf_snack3 = ONode.deserialize<Ret<Out>>(ret,typeOf_T)
val typeOf_fastJson2 = JSON.parseObject<Ret<Out>>(ret, typeOf_T)
val typeOf_gson = Gson().fromJson<Ret<Out>>(ret, typeOf_T)
}
data class Ret<T>(
var code:String?=null,
var msg:String?=null,
var data:T?=null
)
data class Out(
var id:String?=null,
var name:String?=null,
var inner:Inner?=null
)
data class Inner(
var id:String?=null,
var name:String?=null,
var innerdata:List<String>?=null
)
使用
typeOf
传递给反序列化的Type参数即可().javaType
不过使用这个方法得在调用方法上面加上@OptIn(ExperimentalStdlibApi::class)
data class 用起来确实方便,但是由于kt的设计思想,data class 会被编译成 final class 。就是说这个数据类型不能被继承了。
也就导致上述的问题,基本上官方给的使用匿名内部类传递泛型的方法不能使用,就是下面这种:
// 取自snack3文档
List<UserModel> list = ONode.deserialize(json, (new ArrayList<UserModel>(){}).getClass());
kt里得用object:
来实现匿名内部类,类似这种
val list: List<UserModel> = ONode.deserialize<List<UserModel>>(json, object : ArrayList<UserModel>() {}.javaClass)
如果使用官方的方法,就得让接收结果的类变成open class
虽然只变最上面那层就可以,但是写起来就有点怪,毕竟有个空的类显示的放在那里。
所以如果想要通用结果类和数据类都是data class
那最好是使用typeOf
传递Type
因为最开始没意识到kt里还能直接获取.javaType
使用了Solon框架,框架默认使用了Snack3。
所以利用TypeRef
和kt的泛型实化原理封装了一个方法:
inline fun <reified T> gType(): Type? {
return object : TypeRef<T>() {}.type
}
声明成顶层函数即可
使用的时候调用函数就行了:
val ret= ONode.deserialize<Ret<Out>>(ret,gType<Ret<Out>>())
这种方式本质上也是使用了匿名内部类,但内部类声明的地方至少不会出现在代码显示调用的地方。
不过这种方式依赖序列化框架,TypeRef
是Snack3提供的,GSON里好像叫TypeToken
。
喜欢这种方式的也可以自行封装一下。