Android Kotlin中如何用Retrofit解析含嵌套JSON的公交API响应
问题描述
我正在学习Android开发,制作一款公交到站时间应用,通过调用本地API获取下3班公交的到站时间,使用Kotlin和Jetpack Compose开发。尝试用Data Class存储API返回的JSON结果,但处理NextBus、NextBus2、NextBus3这些嵌套JSON对象时可能存在错误,附上了SingaporeBus.kt的代码,希望得到正确的处理方法。
API返回示例
{ "odata.metadata": "http://datamall2.mytransport.sg/ltaodataservice/$metadata#BusArrivalv2/@Element", "BusStopCode": "65199", "Services": [ { "ServiceNo": "89", "Operator": "SBST", "NextBus": { "OriginCode": "64009", "DestinationCode": "64009", "EstimatedArrival": "2022-12-22T22:15:06+08:00", "Latitude": "1.3947326666666666", "Longitude": "103.89898083333334", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", "Type": "DD" }, "NextBus2": { "OriginCode": "64009", "DestinationCode": "64009", "EstimatedArrival": "2022-12-22T22:31:36+08:00", "Latitude": "0", "Longitude": "0", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", "Type": "DD" }, "NextBus3": { "OriginCode": "64009", "DestinationCode": "64009", "EstimatedArrival": "2022-12-22T22:47:51+08:00", "Latitude": "0", "Longitude": "0", "VisitNumber": "1", "Load": "SEA", "Feature": "WAB", "Type": "DD" } } ] }
原SingaporeBus.kt代码
package com.example.busexpress.network import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @Serializable data class SingaporeBus( @SerialName(value = "ServiceNo") val busServiceNumber: String, // Bus Arrival Timings @SerialName(value = "NextBus") val nextBus1: Json, @SerialName(value = "NextBus2") val nextBus2: Json, @SerialName(value = "NextBus3") val nextBus3: Json ) @Serializable data class NextBusTiming( // Date-Time expressed in the UTC standard, GMT+8 for Singapore Standard Time (SST) @SerialName(value = "EstimatedArrival") val estimatedArrival: String, @SerialName(value = "OriginCode") val startingBusStop: String, @SerialName(value = "DestinationCode") val endingBusStop: String, // Current Bus Occupancy Levels @SerialName(value = "Load") val busOccupancyLevels: String, // Wheelchair Support @SerialName(value = "Feature") val wheelchairAccessible: String, // Bus Type @SerialName(value = "Type") val vehicleType: String, // Bus Approximate Location @SerialName(value = "Latitude") val latitude: String, @SerialName(value = "Longitude") val longitude: String )
解决方案
你的问题在于把嵌套的JSON对象用Json类型存储,而没有直接使用已定义的NextBusTiming数据类。另外原数据类未覆盖API返回的完整结构,需要补全整个层级的Data Class。
修正后的完整代码
package com.example.busexpress.network import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable // 最外层的API返回结构 @Serializable data class BusArrivalResponse( @SerialName("odata.metadata") val metadata: String, @SerialName("BusStopCode") val busStopCode: String, @SerialName("Services") val services: List<BusService> ) // 单条公交线路的信息 @Serializable data class BusService( @SerialName("ServiceNo") val serviceNumber: String, @SerialName("Operator") val operator: String, @SerialName("NextBus") val nextBus: NextBusTiming?, @SerialName("NextBus2") val nextBus2: NextBusTiming?, @SerialName("NextBus3") val nextBus3: NextBusTiming? ) // 单班车的到站信息 @Serializable data class NextBusTiming( @SerialName("EstimatedArrival") val estimatedArrival: String, @SerialName("OriginCode") val startingBusStop: String, @SerialName("DestinationCode") val endingBusStop: String, @SerialName("Load") val busOccupancyLevels: String, @SerialName("Feature") val wheelchairAccessible: String, @SerialName("Type") val vehicleType: String, @SerialName("Latitude") val latitude: String, @SerialName("Longitude") val longitude: String, @SerialName("VisitNumber") val visitNumber: String // 补充API返回中存在的字段 )
关键修改点说明
- 新增
BusArrivalResponse作为最外层数据类,对应API返回的完整结构,包含BusStopCode和Services数组。 - 将原
SingaporeBus改名为BusService,补充了API返回里的Operator字段,同时把nextBus系列字段的类型从Json替换为NextBusTiming?(用可空类型适配API可能返回空值的情况)。 - 给
NextBusTiming补充了API返回中存在的VisitNumber字段,避免序列化时丢失数据。
内容的提问来源于stack exchange,提问作者Michelin_Boi
相关产品推荐
相关产品推荐

