Android Kotlin:Data Class中JSON嵌套对象的声明与映射问题
解决Kotlin中API响应模型嵌套对象声明与映射问题
一、正确声明嵌套的Remote响应模型
先确保所有嵌套对象的数据类定义正确且可访问,规避拼写、作用域类的低级问题。
假设你的目标JSON结构如下:
{ "id": "topic_1", "title": "基础语法", "assetsStreak": { "currentStreak": 7, "maxStreak": 14 }, "testing": { "totalQuestions": 20, "completed": 12 } }
1. 定义嵌套对象的顶层数据类
将嵌套对象的模型定义为顶层类(或与父模型同包/同文件,确保可访问):
// AssetStreak的Remote响应模型 data class AssetStreakRemoteResponse( val currentStreak: Int, val maxStreak: Int ) // Testing的Remote响应模型 data class TestingRemoteResponse( val totalQuestions: Int, val completed: Int )
2. 在父模型中引用嵌套类
在TopicsItemRemoteResponseModel中直接声明嵌套字段,注意类名拼写完全一致:
data class TopicsItemRemoteResponseModel( val id: String, val title: String, val assetsStreak: AssetStreakRemoteResponse?, // 可空性根据JSON实际情况调整 val testing: TestingRemoteResponse? )
如果仍出现unresolved reference错误,排查这几点:
- 嵌套类的拼写是否和引用时完全匹配(大小写、单词拼写都要一致)
- 嵌套类是否在同一包下,或是否已正确导入(比如
import com.yourpackage.AssetStreakRemoteResponse) - 不要将嵌套类定义为父类的
private内部类,除非你明确需要内部类作用域
二、Remote模型到Domain模型的映射
Domain层模型要与Remote层解耦,只保留业务所需字段。
1. 定义Domain层模型
// Domain层的AssetStreak data class AssetStreak( val currentStreak: Int, val maxStreak: Int ) // Domain层的Testing data class Testing( val totalCompleted: Int, val totalQuestions: Int ) // Domain层的TopicsItem data class TopicsItem( val id: String, val title: String, val streak: AssetStreak?, val testProgress: Testing? )
2. 编写映射扩展函数
用Kotlin扩展函数实现Remote到Domain的转换,简洁直观:
// Remote的AssetStreak转Domain fun AssetStreakRemoteResponse.toDomain(): AssetStreak { return AssetStreak( currentStreak = this.currentStreak, maxStreak = this.maxStreak ) } // Remote的Testing转Domain fun TestingRemoteResponse.toDomain(): Testing { return Testing( totalCompleted = this.completed, totalQuestions = this.totalQuestions ) } // Remote的TopicsItem转Domain fun TopicsItemRemoteResponseModel.toDomain(): TopicsItem { return TopicsItem( id = this.id, title = this.title, streak = this.assetsStreak?.toDomain(), testProgress = this.testing?.toDomain() ) }
3. 使用映射
在Repository或数据处理层调用转换逻辑:
// 假设从API获取到Remote模型实例 val remoteModel: TopicsItemRemoteResponseModel = apiService.getTopics() val domainModel: TopicsItem = remoteModel.toDomain()
额外注意事项
- 如果使用Retrofit/Gson等序列化库,确保嵌套类的字段与JSON键名匹配,或用
@SerializedName指定映射关系(比如JSON键为assets_streak,则字段需加@SerializedName("assets_streak")) - 若JSON中嵌套对象可能为null,Remote模型的字段要声明为可空类型(
?),避免序列化崩溃
内容的提问来源于stack exchange,提问作者ignos555
相关产品推荐
相关产品推荐

