Retrofit 2.3.0如何处理嵌套JSON?新手求助解析方法
Hey there! I totally get how frustrating it can be to wrap your head around nested JSON parsing with Retrofit when you're just starting out—been there, done that. Let me walk you through this step by step with concrete examples to make it crystal clear.
The core rule here is: every nested object in your JSON gets its own corresponding class. Let’s use a sample nested JSON to illustrate:
{
"user": {
"id": 123,
"full_name": "Salman Khan",
"contact_info": {
"email": "salman@example.com",
"phone": "1234567890"
}
},
"request_status": "success"
}
For Kotlin (Recommended for Android)
We use data classes since they’re concise and auto-generate equals/hashcode/toString methods:
// Outer-most response class data class ApiResponse( val user: User, @SerializedName("request_status") // Use this if JSON key != class field name val requestStatus: String ) // Nested User class data class User( val id: Int, @SerializedName("full_name") val fullName: String, @SerializedName("contact_info") val contactInfo: ContactInfo ) // Innermost ContactInfo class data class ContactInfo( val email: String, val phone: String )
For Java
Create POJO classes with standard getters and setters:
public class ApiResponse { private User user; @SerializedName("request_status") private String requestStatus; // Getters & Setters public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getRequestStatus() { return requestStatus; } public void setRequestStatus(String requestStatus) { this.requestStatus = requestStatus; } } public class User { private int id; @SerializedName("full_name") private String fullName; @SerializedName("contact_info") private ContactInfo contactInfo; // Getters & Setters public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } public ContactInfo getContactInfo() { return contactInfo; } public void setContactInfo(ContactInfo contactInfo) { this.contactInfo = contactInfo; } } public class ContactInfo { private String email; private String phone; // Getters & Setters public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
Define your API endpoint to return the outer-most data class we just created:
Kotlin (with Coroutines)
interface UserApiService { @GET("users/profile") // Replace with your actual endpoint path suspend fun getUserProfile(): Response<ApiResponse> }
Java (with Callbacks)
public interface UserApiService { @GET("users/profile") Call<ApiResponse> getUserProfile(); }
Kotlin Example (Coroutines)
// Initialize Retrofit instance val retrofit = Retrofit.Builder() .baseUrl("https://your-api-base-url.com/") // Replace with your API's base URL .addConverterFactory(GsonConverterFactory.create()) // Gson handles the parsing work .build() val apiService = retrofit.create(UserApiService::class.java) // Launch a coroutine to make the request (run on background thread) CoroutineScope(Dispatchers.IO).launch { try { val response = apiService.getUserProfile() if (response.isSuccessful) { val apiResponse = response.body() apiResponse?.let { // Access nested data step by step val userName = it.user.fullName val userEmail = it.user.contactInfo.email println("User: $userName | Email: $userEmail") } } else { println("Request failed with code: ${response.code()}") } } catch (e: Exception) { e.printStackTrace() } }
Java Example (Callback)
// Initialize Retrofit instance Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://your-api-base-url.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); UserApiService apiService = retrofit.create(UserApiService.class); // Enqueue the request to run asynchronously Call<ApiResponse> call = apiService.getUserProfile(); call.enqueue(new Callback<ApiResponse>() { @Override public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) { if (response.isSuccessful()) { ApiResponse apiResponse = response.body(); if (apiResponse != null) { String userName = apiResponse.getUser().getFullName(); String userEmail = apiResponse.getUser().getContactInfo().getEmail(); System.out.println("User: " + userName + " | Email: " + userEmail); } } else { System.out.println("Request failed with code: " + response.code()); } } @Override public void onFailure(Call<ApiResponse> call, Throwable t) { t.printStackTrace(); } });
- Match Field Names: Ensure your class field names exactly match the JSON keys. If they don’t, use the
@SerializedNameannotation (as shown earlier) to map them correctly. - Handle Nullable Fields: If a nested object might be missing (null in JSON), mark the corresponding class field as nullable in Kotlin (add
?, e.g.,val contactInfo: ContactInfo?)—Gson will automatically set it to null if absent. - Use the Right Converter: We used Gson here, but Retrofit also supports Moshi, Jackson, etc. Pick the one you’re comfortable with—all work the same way for nested structures.
That’s it! Once your data classes mirror the JSON’s nested structure, Retrofit and Gson do all the heavy lifting for you. No manual JSON parsing needed.
内容的提问来源于stack exchange,提问作者Salman Khan

