Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json Kotlinx序列化:如何绕过具体化的typeargs进行反序列化?_Json_Kotlin_Generics_Kotlinx.serialization_Kotlin Reified Type Parameters - Fatal编程技术网

Json Kotlinx序列化:如何绕过具体化的typeargs进行反序列化?

Json Kotlinx序列化:如何绕过具体化的typeargs进行反序列化?,json,kotlin,generics,kotlinx.serialization,kotlin-reified-type-parameters,Json,Kotlin,Generics,Kotlinx.serialization,Kotlin Reified Type Parameters,实际上,主要的问题仍然是Kotlin中的类没有具体化的typeargs。但这就是为什么在这个具体案例中我会感到困扰的原因: 假设您有一个包装类wrapper,它接受一个字符串内容和一个类*类型,并且可以通过调用函数getObj(),将类类型的对象按需解析为JSON: 类包装器(私有val内容:String,/*私有val类型:KClass*/){ fun getObj():T{ // ? } } 我想使用kotlinx.serialization。现在,你可能已经注意到我以前是如何在“clas

实际上,主要的问题仍然是Kotlin中的类没有具体化的typeargs。但这就是为什么在这个具体案例中我会感到困扰的原因:

假设您有一个包装类
wrapper
,它接受一个字符串
内容
和一个类*
类型
,并且可以通过调用函数
getObj()
,将类
类型
的对象按需解析为JSON:

类包装器(私有val内容:String,/*私有val类型:KClass*/){ fun getObj():T{ // ? } } 我想使用kotlinx.serialization。现在,你可能已经注意到我以前是如何在“class”后面加上星号的。原因如下:是的,
Wrapper
必须以某种方式获取目标类,但是如何实现呢?它应该只是typearg(因为类型erausre而不起作用)还是
KClass
引用(因为我需要一个具体化的typearg而不起作用)

就我所知,将通用JSON解码为可序列化目标类的唯一方法是使用
JSON.decodeFromString(content)
,其中
T
是目标类型,
content
是JSON字符串。现在,
T
被定义为具体化(以便可以在运行时处理该类型),并且只能用另一个具体化的typearg或实际的类引用填充。我不能使用另一个具体化的typearg,因为我在一个类的上下文中,并且一个类不能有具体化的typearg。我也不能使用实际的类引用,因为类的用户应该能够使用不同的目标来构造它,例如,他们决定目标是什么,而不是我


那么,如何使用kotlinx.serialization实现这一点呢?甚至可能吗?

好的,所以还没有人回答这个问题,但我也在r/Kotlin子Reddit中发布了这个问题

事实上,我在那里得到了一个答案(归功于u/JakeWharton),因为你可能会通过谷歌搜索到这个问题,所以你可能会很高兴在这里找到答案。下面是我试图解释的答案:

因此,基本上,kotlinx序列化确实不适用于
KClass
es。但是当您考虑它时,您只需要
KClass
来确定如何序列化它。由于这是在使用KXS时在编译时确定的,所以实际上只需要传递序列化程序(定义如何序列化/反序列化类的实际策略)。通过调用
.serializer()
,可以为每个用
@Serializable
注释的类获取序列化程序;结果将是
KSerializer
类型。因此,与其

类包装器(私有val内容:字符串,私有val类型:KClass) 并通过

val wrapper=wrapper(“{}”,Foo::class)
您可以这样做:

类包装器(私有val内容:字符串,私有val序列化程序:KSerializer) 然后像这样构造它:

val wrapper=wrapper(“{}”,Foo.serializer())
(假设
Foo
@Serializable
注释)

然后可以使用
KSerializer
而不是typearg进行序列化和反序列化,如下所示:

val obj:T=Json.decodeFromString(序列化程序,“[您的Json字符串]”)
val str:String=Json.encodeToString(序列化程序,obj)

就这样!只需通过
KSerializer
替换常规的
(K)类
方法,它将与KXS一起工作。

对不起,我不明白使用
KClass
有什么问题,就像您在构造函数中显示的那样(我认为它也应该是
KClass
),序列化不采用
KClass
es,因为它是一个多平台库,而且反射只在JVM上可用,所以它也可以不使用反射。如果它能与
KClass
一起工作,我会使用它。因此,如果可能的话,请纠正我并告诉我怎么做it@userAFAIK内联类仍然是实验性的(虽然这不是一个大问题),但真正的问题是,当然,我想做的不仅仅是一个简单的包装类。问题中的包装器类仅显示问题的最简化解释。实际上,除其他外,该类还应该进行一些缓存。我认为很明显,对于缓存,我需要不止一个字段。因此,我不能使用内联类