使用Retrofit2的Android应用JSON查询异常,无法深度解析数据
Hey there! Let’s figure out why you’re hitting that onFailure when trying to pull the stormName field—Retrofit + GSON parsing issues usually boil down to mismatched entity classes or hidden JSON structure quirks. Let’s break this down step by step:
1. First: Fix the Entity Class <-> JSON Structure Mismatch
This is the #1 culprit for parsing failures. Let’s align your data classes with the actual JSON hierarchy:
- From the JSON path you mentioned (
$.currenthurricane.[stormInfo].stormName), double-check ifstormInfois a single object or an array in the raw JSON. If it’s a single object (not wrapped in[]), definingstormInfoas aList<StormInfo>in yourCurrentHurricaneclass will break parsing—GSON can’t convert an object to a list. - Also, ensure field names match exactly (or use
@SerializedNameif you’re using different variable names in Kotlin).
Here’s a corrected example based on typical hurricane API structures:
data class Cyclones( val currenthurricane: List<CurrentHurricane> ) data class CurrentHurricane( @SerializedName("stormInfo") // Match JSON field name exactly val stormInfo: StormInfo // Use a single object, not List, if stormInfo isn't an array ) data class StormInfo( @SerializedName("stormName") val stormName: String )
2. Debug the Exact Failure Reason
Stop guessing—get the real error message from onFailure:
override fun onFailure(call: Call<Cyclones>, t: Throwable) { t.printStackTrace() // Check Logcat for details like "Expected BEGIN_OBJECT but was BEGIN_ARRAY" }
This will tell you exactly where the parsing broke (e.g., array vs object mismatch, missing fields).
3. Test Parsing Step-by-Step
Don’t jump straight to stormName—validate each layer first:
override fun onResponse(call: Call<Cyclones>, response: Response<Cyclones>) { if (response.isSuccessful) { val cyclones = response.body() // First check if currenthurricane exists and has data cyclones?.currenthurricane?.let { hurricaneList -> if (hurricaneList.isNotEmpty()) { // Test the first hurricane entry first (avoid index out of bounds) val firstHurricane = hurricaneList[0] // Print the hurricane object to see if stormInfo is parsed correctly Log.d("ParsingTest", "First hurricane: $firstHurricane") // Now try to get stormName firstHurricane.stormInfo?.stormName?.let { name -> Log.d("StormName", "Found: $name") } ?: Log.d("ParsingTest", "stormInfo or stormName is null") } } } }
4. Double-Check Retrofit Setup
Make sure you’ve added the GSON converter factory to your Retrofit instance—without it, Retrofit can’t parse JSON into your data classes:
val retrofit = Retrofit.Builder() .baseUrl("https://api.myjson.com/") .addConverterFactory(GsonConverterFactory.create()) .build()
5. Once Parsing Works: Connect to RecyclerView
Once you can reliably fetch stormName (or full hurricane objects), pass the list to your RecyclerView adapter:
// In your onResponse cyclones?.currenthurricane?.let { hurricaneList -> val adapter = HurricaneAdapter(hurricaneList) recyclerView.adapter = adapter }
Your adapter can then extract stormName from each CurrentHurricane item in onBindViewHolder.
内容的提问来源于stack exchange,提问作者CB Midkiff

