CodexBloom - Programming Q&A Platform

Handling JSON Parsing Issues with Moshi in Android 14 When Using Custom Types

πŸ‘€ Views: 1663 πŸ’¬ Answers: 1 πŸ“… Created: 2025-08-06
android moshi json retrofit serialization Kotlin

I'm trying to implement I'm relatively new to this, so bear with me... I'm encountering a frustrating issue while trying to parse a JSON response using Moshi in my Android 14 application. The JSON I receive from the API contains a field that can either be a string or an object, depending on the response. For example: ```json { "userId": 1, "details": { "name": "John Doe", "age": 30 } } ``` But sometimes it can be like this: ```json { "userId": 1, "details": "basic info" } ``` I've set up my data classes using Moshi annotations, but I'm facing a `JsonDataException` when the `details` field is a string instead of an object. Here’s a snippet of my code: ```kotlin @JsonClass(generateAdapter = true) data class UserResponse( val userId: Int, val details: DetailsType ) sealed class DetailsType { @JsonClass(generateAdapter = true) data class UserDetails(val name: String, val age: Int) : DetailsType() data class BasicInfo(val info: String) : DetailsType() } ``` I also tried implementing a custom adapter for `DetailsType` to handle the different formats, but I'm still getting the same error: ```kotlin class DetailsTypeAdapter { @FromJson fun fromJson(json: Any): DetailsType { return when (json) { is Map<*, *> -> Moshi.Builder().build().adapter(UserDetails::class.java).fromJsonValue(json) as? DetailsType ?: BasicInfo("No info") is String -> BasicInfo(json) else -> throw JsonDataException("Unexpected JSON format for details") } } } ``` In my Retrofit setup, I'm using this adapter: ```kotlin val moshi = Moshi.Builder() .add(DetailsTypeAdapter()) .build() val retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(MoshiConverterFactory.create(moshi)) .build() ``` Despite these efforts, I'm still running into the error: `com.squareup.moshi.JsonDataException: Expected a map but was a string at path $.details` when the `details` field is a string. I’ve tried logging the response before parsing, and it looks correct, but I must be missing something in the way Moshi handles the deserialization. Any suggestions on how to effectively handle this scenario? I've been using Kotlin for about a year now. How would you solve this?