Ktor:使用List作为Multiplatform中的root序列化/反序列化JSON

时间:2018-10-24 14:05:48

标签: json serialization kotlin ktor kotlin-multiplatform

我们如何将kotlin.serialize与Ktor的HttpClient一起使用以反序列化/序列化以列表为根的JSON?我正在创建HttpClient,如下所示:

AudioPlayer

似乎我需要为List设置setMapper,但是对于泛型来说这是不可能的。我看到我可以使用MyClass.serializer()。list获得它的序列化器,但是将其注册为对HTTP请求进行反序列化/序列化并不是一件容易的事。有谁知道一个好的解决方案?

4 个答案:

答案 0 :(得分:4)

您可以编写包装器和自定义序列化器:

Option Explicit

Private Sub CommandButton1_Click()

        Dim LastRowH As Long, i As Long, LastRowA As Long

LastRowH = Worksheets("OFCE").Cells(Worksheets("OFCE").Rows.Count, "H").End(xlUp).Row

For i = 1 To LastRowH

    If Worksheets("OFCE").Cells(i, "H").Value = "Yes" Then

        LastRowH = Worksheets("Dashboard").Cells(Worksheets("Dashboard").Rows.Count, "A").End(xlUp).Row

        Worksheets("Dashboard").Cells(LastRowH + 1, 1).Value = Worksheets("OFCE").Cells(i, 1).Value

    End If

Next i

End Sub

注册:

@Serializable
class MyClassList(
    val items: List<MyClass>
) {

    @Serializer(MyClassList::class)
    companion object : KSerializer<MyClassList> {

        override val descriptor = StringDescriptor.withName("MyClassList")

        override fun serialize(output: Encoder, obj: MyClassList) {
            MyClass.serializer().list.serialize(output, obj.items)
        }

        override fun deserialize(input: Decoder): MyClassList {
            return MyClassList(MyClass.serializer().list.deserialize(input))
        }
    }
}

并使用:

HttpClient {
    install(JsonFeature) {
        serializer = KotlinxSerializer().apply {
            setMapper(MyClassList::class, MyClassList.serializer())
        }
    }
}

答案 1 :(得分:3)

还没有办法在kotlinx.serialization中对这样的JSON进行(反)序列化。

对于序列化,您可以尝试执行以下操作:

MainWindow

并且没有已知的方法来获取列表反序列化器。

答案 2 :(得分:0)

这更多是一种解决方法,但是在逐步完成KotlinxSerializer代码之后,我看不到其他任何解决方法。例如,如果您查看KotlinxSerializer.read(),您会发现它尝试基于mapper查找type,但是在这种情况下,它只是kotlin.collections.List并且无法解析。我曾尝试调用类似setListMapper(MyClass::class, MyClass.serializer())的方法,但这仅适用于序列化(通过lookupSerializerByData中的write方法使用)

override suspend fun read(type: TypeInfo, response: HttpResponse): Any {
    val mapper = lookupSerializerByType(type.type)
    val text = response.readText()

    @Suppress("UNCHECKED_CAST")
    return json.parse(mapper as KSerializer<Any>, text)
}

所以,我最终要做的是(请注意serializer().list通话)

suspend fun fetchBusStops(): List<BusStop> {
    val jsonArrayString = client.get<String> {
        url("$baseUrl/stops.json")
    }

    return JSON.nonstrict.parse(BusStop.serializer().list, jsonArrayString)
}

不理想,显然没有使用JsonFeature

答案 3 :(得分:0)

我碰巧在Kotlin / JS上遇到了同样的问题,并设法通过以下方式解决了这个问题:

private val client = HttpClient(Js) {
  install(JsonFeature) {
    serializer = KotlinxSerializer().apply {
      register(User.serializer().list)
    }
  }
}
...
private suspend fun fetchUsers(): Sequence<User> =
    client.get<List<User>> {
      url("$baseUrl/users")
    }.asSequence()

希望这会有所帮助:)