改造+ gson反序列化器:返回数组中

我有api返回json:

{"countries":[{"id":1,"name":"Australia"},{"id":2,"name":"Austria"}, ... ]} 

我写模特班(Kotlin lang)

 data class Country(val id: Int, val name: String) 

我想要使​​用retorift返回List <Models.Country>,从json中的“countries”字段请求

我下面写:

 interface DictService { @GET("/json/countries") public fun countries(): Observable<List<Models.Country>> companion object { fun create() : DictService { val gsonBuilder = GsonBuilder() val listType = object : TypeToken<List<Models.Country>>(){}.type gsonBuilder.registerTypeAdapter(listType, CountriesDeserializer) gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) val service = Retrofit.Builder() .baseUrl("...") .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create())) .build() return service.create(DictService::class.java) } } object CountriesDeserializer : JsonDeserializer<List<Models.Country>> { override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): List<Models.Country>? { val res = ArrayList<Models.Country>() if(json!=null) { val countries = json.asJsonObject.get("countries") if (countries.isJsonArray()) { for (elem: JsonElement in countries.asJsonArray) { res.add(Gson().fromJson(elem, Models.Country::class.java)) } } } return null; } } } 

但是我得到的错误:java.lang.IllegalStateException:期望BEGIN_ARRAY,但BEGIN_OBJECT行1列2路径$ CountriesDeserializer代码不要执行,甚至! 他们想从我那里得到什么?

也许我需要写我自己的TypeAdapterFactory?

我不想使用模型类

 class Countries { public List<Country> countries; } 

如果你的意图是简化接口并隐藏中间包装对象,我想最简单的方法就是向DictService添加一个扩展方法, DictService所示:

 interface DictService { @GET("/json/countries") fun _countries(): Observable<Countries> } fun DictService.countries() = _countries().map { it.countries } data class Countries(val countries: List<Country> = listOf()) 

然后可以如下使用:

 val countries:Observable<List<Country>> = dictService.countries() 

我找到了方法:

 object CountriesTypeFactory : TypeAdapterFactory { override fun <T : Any?> create(gson: Gson?, type: TypeToken<T>?): TypeAdapter<T>? { val delegate = gson?.getDelegateAdapter(this, type) val elementAdapter = gson?.getAdapter(JsonElement::class.java) return object : TypeAdapter<T>() { @Throws(IOException::class) override fun write(outjs: JsonWriter, value: T) { delegate?.write(outjs, value) } @Throws(IOException::class) override fun read(injs: JsonReader): T { var jsonElement = elementAdapter!!.read(injs) if (jsonElement.isJsonObject) { val jsonObject = jsonElement.asJsonObject if (jsonObject.has("countries") && jsonObject.get("countries").isJsonArray) { jsonElement = jsonObject.get("countries") } } return delegate!!.fromJsonTree(jsonElement) } }.nullSafe() } } 

但是,我认为,这样的问题是非常复杂的决定。 还有另一种更简单的方法吗?

另一个:我发现我的初始代码从开始meassage中的错误! 它工作正常,如果替换ListList ArrayList!

我会用杰克逊来完成这个任务。 试试这个https://github.com/FasterXML/jackson-module-kotlin

 val mapper = jacksonObjectMapper() data class Country(val id: Int, val name: String) // USAGE: val country = mapper.readValue<Country>(jsonString)