Kotlin Json 序列化

Kotlin可以直接调用 Java(也就可以直接使用 Jackson, Gson 等json库),不过我看到有 official 的序列化库,于是研究了一下。

重点看了下多态的序列化,确实非常简洁,先上代码感受一下:

@Serializable
sealed interface Reply
@Serializable
@SerialName("text")
class TextReply(val content: String): Reply
@Serializable
@SerialName("card")
class CardReply(val content: String, val cardId: Long = 1L): Reply
fun main() {
 val reply: Reply = CardReply("A card", 2L)
 // 序列化
 val jsonString = Json.encodeToString(reply)
 println(jsonString)
 // 反序列化,隐式
 val decodedReply: Reply = Json.decodeFromString(jsonString)
 println(decodedReply)
 // 显式
 println( Json.decodeFromString<Reply>(jsonString) )
}

Output:

{"type":"card","content":"A card","cardId":2}
[email protected][email protected]

CardReply & TextReply 实现了 Reply,可以看到序列化结果自动加上了类型标识"type": "card"


再来看看泛型的序列化,同样十分简洁:

fun main() {
 // 列表序列化
 val jsonList = Json.encodeToString(
 listOf(CardReply("A card"), TextReply("A text"))
 )
 println(jsonList)
 // 列表反序列化
 val replies: List<Reply> = Json.decodeFromString(jsonList)
 println(replies)
}

Output:

[{"type":"card","content":"A card"},{"type":"text","content":"A text"}]
[[email protected], [email protected]]

可以看到,泛型没有丢失,good。

用过 Jackson 的同学应该知道这个神坑,给个单元测试感受一下:

public class ReplyTest {
 @JsonTypeInfo(
 use = JsonTypeInfo.Id.NAME,
 defaultImpl = CardReply.class
 )
 @JsonSubTypes({
 @JsonSubTypes.Type(value = CardReply.class, name = "card")
 })
 interface Reply { }
 static class CardReply implements Reply { }
 @Test
 void fuck() throws JsonProcessingException {
 System.out.println( JsonUtil.toStr(new CardReply()) );
 String json = JsonUtil.toStr( Collections.singletonList(new CardReply()) );
 System.out.println(json);
 }
}

Output:

{ "@type" : "card" }
[ { } ]

可以看到,List<Reply>序列化结果丢失了泛型,令人沮丧。

至此,Kotlin 给人感觉还不错,代码简洁,对多态支持良好。


详情请参考官方库:https://github.com/Kotlin/kot...

作者:骚铭科技原文地址:https://segmentfault.com/a/1190000042700078

%s 个评论

要回复文章请先登录注册