我正在访问具有两种端点的JSON API:
第一种返回相同类型的对象列表(症状,慢性疾病...)
第二种(搜索功能)返回混合混合的不同类型对象的列表(这些类型与第一种API可以返回的类型相同)
在第二种情况下,列表的每个项目都有一个类型字段,该字段告诉对象的类型。在第一种情况下,该字段不存在。
我想将默认的反序列化器用于第一种API,并将自定义反序列化器用于第二种API。有可能吗?
如果我仅使用默认的反序列化器,则第一种API调用将起作用,但无法执行搜索。
如果启用以下解串器,搜索将起作用,但是在使用第一种API时也会使用解串器,并且由于缺少类型字段而失败。
我要使用的自定义解串器:
class SearchableItemDeserializer : JsonDeserializer<SearchableItem>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SearchableItem {
val root : JsonNode = p.readValueAsTree()
val type : String = root.get("type").asText()
when(type){
"symptom" -> {
return ObjectMapper().readValue(root.asText(), Symptom::class.java)
}
"symptom_group" -> {
return ObjectMapper().readValue(root.asText(), SymptomGroup::class.java)
}
"diagnosis" -> {
return ObjectMapper().readValue(root.asText(), Diagnose::class.java)
}
"chronic_disease" -> {
return ObjectMapper().readValue(root.asText(), ChronicDisease::class.java)
}
}
throw Exception("Unable to deserialize type $type")
}
}
症状,症状组,诊断和慢性疾病共有的接口:
@JsonDeserialize(using = SearchableItemDeserializer::class)
interface SearchableItem
答案 0 :(得分:1)
有可能。您可以扩展Converter.Factory来创建您的自定义转换器。可能最愚蠢和直接的方法是在“ requestBodyConverter”或“ responseBodyConverter”方法中添加对特定改装批注的检查。
类似的东西:
class CustomConverter : Converter.Factory() {
override fun responseBodyConverter(type: Type,
annotations: Array<Annotation>,
retrofit: Retrofit): Converter<ResponseBody, *>? {
return responseConverter(*annotations)
.responseBodyConverter(type, annotations, retrofit)
}
private fun responseConverter(vararg methodAnnotations: Annotation): Converter.Factory {
return when {
endpoint1(*methodAnnotations) -> converter1
endpoint2(*methodAnnotations) -> converter2
else -> defaultConverter
}
}
override fun requestBodyConverter(type: Type,
parameterAnnotations: Array<Annotation>,
methodAnnotations: Array<Annotation>,
retrofit: Retrofit): Converter<*, RequestBody>? {
//same approach here
}
fun endpoint1(vararg annotations: Annotation): Boolean {
//condition check here
}
fun endpoint2(vararg annotations: Annotation): Boolean {
//and here (if needed)
}
只需添加端点1/2的实现(可能只是将@Get()内容与某些模式或类似内容进行比较),并对requestConverter重复相同的指令即可。
准备好后,只需将其添加到改造中即可
return Retrofit.Builder()
.baseUrl(url)
.client(client)
.addConverterFactory(CustomConverter())
.build()