Ktor自定义json对象反序列化
Posted
技术标签:
【中文标题】Ktor自定义json对象反序列化【英文标题】:Ktor custom json object deserialization 【发布时间】:2021-06-24 17:31:24 【问题描述】:我是 Ktor 的新手,我来自 Retrofit 背景,我想映射这个 json:
"key1": "value1",
"key2": "value2",
...
into(其实我不需要把json本身映射成反序列化的版本):
[
"key1": "value1",
"key2": "value2",
...
]
@Serializable
data class MyObject(
val member1: String,
val member2: String
)
我在官方文档中看到的示例并没有太大帮助,所以我尝试了类似的方法:
@InternalSerializationApi
object CustomDeserializer : DeserializationStrategy<List<MyObject>>
@ExperimentalSerializationApi
override val descriptor = buildSerialDescriptor("MyObject", PolymorphicKind.OPEN)
element("key", String.serializer().descriptor)
element("value", String.serializer().descriptor)
@ExperimentalSerializationApi
override fun deserialize(decoder: Decoder): List<MyObject> = decoder.decodeStructure(descriptor)
val result = ArrayList<MyObject>()
loop@ while (true)
val index = decodeElementIndex(descriptor)
if (index == DECODE_DONE)
break@loop
else if (index > 1)
throw SerializationException("Unexpected index $index")
else
result.add(MyObject(decodeStringElement(descriptor, index = 0), decodeStringElement(descriptor, index = 1)))
return result
问题:
-
我是在正确的道路上,还是有更好的方法来实现它?
如何将此添加到我的客户? (可能只针对特定请求)
ps:这就是我使用 Gson 的方式(忽略它在 Java 中的事实):
public class MyObjectConverterFactory implements JsonDeserializer<List<MyObject>>
@Override
public List<MyObject> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
List<MyObject> res = new ArrayList<>();
if (json != null && json.getAsJsonObject() != null)
JsonObject object = json.getAsJsonObject();
Set<String> keys = object.keySet();
for (String key : keys)
res.add(new MyObject(key, object.get(key).getAsString()));
return res;
【问题讨论】:
您使用的是kotlinx.serialization
,对吗?为什么插件生成的序列化程序不适合?如果原因是class和json中的字段名不匹配,可以用@SerialName
注解修复:@Serializable data class MyObject(@SerialName("key1") val member1: String, @SerialName("key2") val member2: String)
是的,我正在使用,但问题是我想要一个 List据我从 GSON 实现中获得,您需要从 JSON 反序列化
"key1":"value1","key2":"value2", ...
进入
listOf(MyObject(member1="key1", member2="value1"), MyObject(member1="key2", member2="value2"), ...)
kotlinx.serialization
也可以:
object MyObjectListSerializer : JsonTransformingSerializer<List<MyObject>>(ListSerializer(MyObject.serializer()))
override fun transformDeserialize(element: JsonElement) =
JsonArray((element as JsonObject).entries.map (k, v) ->
buildJsonObject
put("member1", k)
put("member2", v)
)
用法(普通的kotlinx.serialization):
val result = Json.decodeFromString(MyObjectListSerializer, "\"key1\":\"value1\",\"key2\":\"value2\"")
使用(与 Ktor 客户端):
val client = HttpClient
install(JsonFeature)
serializer = KotlinxSerializer(Json
serializersModule = SerializersModule contextual(MyObjectListSerializer)
)
val result = client.get<List<MyObject>>("http://localhost:8000/myObj")
【讨论】:
谢谢!只缺少一件事,我如何将这个MyObjectListSerializer
添加到 ktor 客户端?
更新了我的答案以上是关于Ktor自定义json对象反序列化的主要内容,如果未能解决你的问题,请参考以下文章
C#中使用Newtonsoft.Json序列化和反序列化自定义类对象