Retrofit+Kotlin协程解析邮编API报错:期望对象却得到数组
修复Retrofit解析印度邮编API的JSON数组错误并实现数据展示
错误原因分析
该印度邮编API返回的顶层结构是JSON数组([]包裹),但你的接口定义和数据类期望的是单个JSON对象({}包裹),导致Gson解析时抛出JsonSyntaxException。
代码修复步骤
1. 修正数据类结构
确保数据类完全匹配API返回的JSON结构:
PostOffice.kt
data class PostOffice( val Name: String, val Description: String, val BranchType: String, val DeliveryStatus: String, val Circle: String, val District: String, val Division: String, val Region: String, val State: String, val Country: String )
Pincode.kt
data class Pincode( val Status: String, val PostOffice: List<PostOffice> )
2. 修改API接口定义
将返回类型从单个Pincode改为List<Pincode>,并用Response包裹以处理请求状态:
ApiInterface.kt
import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path interface ApiInterface { @GET("pincode/{pincode}") suspend fun getPincodeDetails(@Path("pincode") pincode: String): Response<List<Pincode>> }
3. 保留ApiClient配置(确保Gson转换器已添加)
ApiClient.kt
import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory object ApiClient { private const val BASE_URL = "https://api.postalpincode.in/" val apiInterface: ApiInterface by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() .create(ApiInterface::class.java) } }
4. 修正MainActivity中的协程调用逻辑
处理数组返回,并添加邮编验证逻辑:
MainActivity.kt
import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 替换为实际EditText的输入内容 val userInputPincode = "110001" if (!validatePincode(userInputPincode)) { Toast.makeText(this, "请输入有效的6位数字邮编", Toast.LENGTH_SHORT).show() return } lifecycleScope.launch { try { val response = ApiClient.apiInterface.getPincodeDetails(userInputPincode) if (response.isSuccessful) { val pincodeList = response.body() pincodeList?.firstOrNull()?.let { pincodeData -> when (pincodeData.Status) { "Success" -> { // 遍历邮政网点数据并展示(可替换为RecyclerView或TextView更新UI) pincodeData.PostOffice.forEach { office -> val village = office.Name val district = office.District val state = office.State Toast.makeText( this@MainActivity, "村庄:$village,地区:$district,邦:$state", Toast.LENGTH_LONG ).show() } } "Error" -> { Toast.makeText(this@MainActivity, "无效的邮编", Toast.LENGTH_SHORT).show() } } } ?: Toast.makeText(this@MainActivity, "未找到数据", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this@MainActivity, "请求失败:${response.code()}", Toast.LENGTH_SHORT).show() } } catch (e: Exception) { Toast.makeText(this@MainActivity, "错误:${e.message}", Toast.LENGTH_SHORT).show() e.printStackTrace() } } } // 印度邮编验证规则:6位纯数字 private fun validatePincode(pincode: String): Boolean { return pincode.length == 6 && pincode.all { it.isDigit() } } }
其他可用的印度邮编API
- 印度邮政官方API:提供官方邮政数据,支持邮编查询、网点信息等,需申请API密钥。
- RapidAPI PinCode API:第三方聚合API,支持批量查询、邮编映射,部分功能需付费。
- GeoNames API:全球地理数据服务,包含印度邮编的地区、经纬度信息,免费版有请求频次限制。
内容的提问来源于stack exchange,提问作者Pinkesh
相关产品推荐
相关产品推荐

