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

时间:2016-05-09 15:11:21

标签: json gson retrofit kotlin

我有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,但在第1行第2行路径为$ BEGIN_OBJECT CountriesDeserializer代码甚至不执行! 他们想要我什么?

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

我不想使用像

这样的模型类
class Countries {
   public List<Country> countries;
}

3 个答案:

答案 0 :(得分:2)

如果您的目的是简化界面并隐藏中间包装器对象,我想最简单的方法是将扩展方法添加到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()

答案 1 :(得分:0)

我找到了方法:

varList :: LExpTree Lukasiewicz -> [String]

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

另一个: 我从初始代码中发现了错误! 如果用ArrayList替换List,它可以正常工作!

答案 2 :(得分:0)

我会用杰克逊完成这项任务。 试试这个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)