【问题标题】:Using Gson in Kotlin to parse JSON array在 Kotlin 中使用 Gson 解析 JSON 数组
【发布时间】:2018-01-18 02:01:51
【问题描述】:

尝试在 Kotlin 中解析 JSON 数组,使其适用于单个 JSON 对象到 WeatherObject 对象(下面的代码 sn-p)

{
"coord": {
    "lon": -2.93,
    "lat": 43.26
},

"weather": [{
    "id": 802,
    "main": "Clouds",
    "description": "scattered clouds",
    "icon": "03d"
}],

"main": {
    "temp": 283.681,
    "temp_min": 283.681,
    "temp_max": 283.681,
    "pressure": 991.72,
    "sea_level": 1034.92,
    "grnd_leve": 991.72,
    "humidity": 98
},
"wind": {
    "speed": 1.07,
    "deg": 144.001
},

"dt": 1429773245,
"id": 3128026,
"name": "Bilbao",
"cod": 200

}

但如果 JSON 是相同 JSON 对象的数组,则不确定如何做同样的事情,即

从 json 数组 [ {}, {} ...] 到 ArrayList

类似:

fun getWeatherObjectArrayFromJson(jsonStr: String): ArrayList<WeatherObject &gt

gsonBuilder.registerTypeAdapter(ArrayList

class WeatherObject {

    var main: String = ""
    var description: String = ""
    var temp: Float = 0.0f
    var tempMax: Float = 0.0f
    var tempMin: Float = 0.0f
    var humidity: Int = 0
    var wind: WindObject? = null

}

class WeatherDeserializer : JsonDeserializer<WeatherObject> {

    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): WeatherObject? {
        val jsonObj = json as JsonObject

        val wheather = WeatherObject()
        val wind = WindObject()

        val jsonWeatherArray = jsonObj.getAsJsonArray("weather").get(0)
        val jsonMainObj = jsonObj.getAsJsonObject("main")
        val jsonWindObj = jsonObj.getAsJsonObject("wind")

        wheather.main = jsonWeatherArray.asJsonObject.get("main").asString
        wheather.description = jsonWeatherArray.asJsonObject.get("description").asString
        wheather.temp = jsonMainObj.get("temp").asFloat
        wheather.tempMax = jsonMainObj.get("temp_max").asFloat
        wheather.tempMin = jsonMainObj.get("temp_min").asFloat
        wheather.humidity = jsonMainObj.get("humidity").asInt
        wind.speed = jsonWindObj.get("speed").asFloat
        wind.deg = jsonWindObj.get("deg").asFloat
        wheather.wind = wind

        return wheather

    }
}

fun getWeatherObjectFromJson(jsonStr: String): WeatherObject {

        var stringReader: StringReader = StringReader(jsonStr)
        var jsonReader: JsonReader = JsonReader(stringReader)

        val gsonBuilder = GsonBuilder().serializeNulls()
        gsonBuilder.registerTypeAdapter(WeatherObject::class.java, WeatherDeserializer())
        val gson = gsonBuilder.create()

        val weather: WeatherObject = gson.fromJson(jsonReader, WeatherObject::class.java)

        return weather
    }

更新:

尝试了 chandil03 的解决方案,它正在工作!把测试的json数组数据和函数放在这里:

试过

fun getWeatherObjectFromJsonArray(jsonArrayStr: String): List<WeatherObject> {

        var stringReader: StringReader = StringReader(jsonStr)
        //var jsonReader: JsonReader = JsonReader(stringReader)

        val gsonBuilder = GsonBuilder().serializeNulls()
        gsonBuilder.registerTypeAdapter(WeatherObject::class.java, WeatherDeserializer())
        val gson = gsonBuilder.create()

        val weatherList: List<WeatherObject> = gson.fromJson(stringReader , Array<WeatherObject>::class.java).toList()
        //val weatherList: List<WeatherObject> = gson.fromJson(jsonReader, Array<WeatherObject>::class.java).toList

        return weatherList
    }

遇到异常

val weatherList: List<WeatherObject> = gson.fromJson(stringReader , Array<WeatherObject>::class.java).toList()

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

json数组数据如下:

[
{
  "coord": {
    "lon": -2.93,
    "lat": 43.26
  },

  "weather": [{
    "id": 802,
    "main": "Clouds",
    "description": "scattered clouds",
    "icon": "03d"
  }],

  "main": {
    "temp": 283.681,
    "temp_min": 283.681,
    "temp_max": 283.681,
    "pressure": 991.72,
    "sea_level": 1034.92,
    "grnd_leve": 991.72,
    "humidity": 98
  },
  "wind": {
    "speed": 1.07,
    "deg": 144.001
  },
  "clouds": {
    "all": 36
  },
  "dt": 1429773245,
  "id": 3128026,
  "name": "Bilbao",
  "cod": 200
}, 

{
  "coord": {
    "lon": -2.93,
    "lat": 43.26
  },

  "weather": [{
    "id": 802,
    "main": "Clouds",
    "description": "scattered clouds",
    "icon": "03d"
  }],

  "main": {
    "temp": 283.681,
    "temp_min": 283.681,
    "temp_max": 283.681,
    "pressure": 991.72,
    "sea_level": 1034.92,
    "grnd_leve": 991.72,
    "humidity": 98
  },
  "wind": {
    "speed": 1.07,
    "deg": 144.001
  },
  "clouds": {
    "all": 36
  },
  "dt": 1429773245,
  "id": 3128026,
  "name": "Bilbao",
  "cod": 200
}
]

【问题讨论】:

    标签: android kotlin gson json-deserialization


    【解决方案1】:

    您需要更改fromJson() 函数调用中的参数,如下所示:

    val weatherList: List<WeatherObject> = gson.fromJson(stringReader , Array<WeatherObject>::class.java).toList()
    

    您需要将Array&lt;WeatherObject&gt;::class.java 传递给类类型,然后将结果转换为List。无需更改registerTypeAdapter() 函数调用。

    检查以下代码:

    fun getWeatherObjectFromJson(jsonStr: String): List<WeatherObject> {
    
            var stringReader: StringReader = StringReader(jsonStr)
            var jsonReader: JsonReader = JsonReader(stringReader)
    
            val gsonBuilder = GsonBuilder().serializeNulls()
            gsonBuilder.registerTypeAdapter(WeatherObject::class.java, WeatherDeserializer())
            val gson = gsonBuilder.create()
    
           val weatherList: List<WeatherObject> = gson.fromJson(stringReader , Array<WeatherObject>::class.java).toList()
    
            return weatherList
        }
    

    【讨论】:

    • 感谢 Chandil03!但是类 WeatherDeserializer 有问题:JsonDeserializer,它处理单个 json 对象,它如何与具有相同 json 对象数组的 json 字符串一起工作,是否需要定义反序列化器的数组版本?
    • @lannyf 不,上面提到的代码只适用于包含天气对象数组的字符串的文件。我已经检查过了。只需一行即可更改。
    • 用你的函数试过,它有异常。我更新了问题中的函数和json数组dat。
    • @lannyf 我也用你给定的 JSON 检查了代码,工作正常,没有任何问题。我可以从您提供的先前输入具有天气对象而不是数组的异常中理解。仅当您期望数组并在 jsonString 输入中提供对象时才会发生该异常。
    • 它正在工作!我的错我仍在使用非数组 dat 进行测试,并认为它正在使用数组数据。非常感谢。不知道为什么 kotlin 在传递 JsonReader 而不是 StringReader 时抱怨。 val weatherList: List = gson.fromJson(jsonReader, Array::class.java).toList
    【解决方案2】:

    另一种扩展功能:

    inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object : TypeToken<T>() {}.type)
    

    用法:

    val str ="[....]"
    val list:List<WeatherObject> = Gson().fromJson<List<WeatherObject>>(str)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-30
      • 2013-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多