Jetpack Compose中嵌套JSON表格数据提取失败问题求助
嵌套JSON数据解析与Jetpack Compose显示问题
我能从普通JSON中提取数据,但处理嵌套结构时遇到了困难,尝试多种方法仍未找到问题所在。以下是相关文件及代码:
JSON文件
[ { "planetId": "earth_id", "planetName": "Earth", "planetTranslations": [ { "planetTransSpa": "Tierra" }, { "planetTransFre": "Terre" }, { "planetTransIta": "Terra" } ] }, { "planetId": "mars_id", "planetName": "Mars", "planetTranslations": [ { "planetTransSpa": "Marte" }, { "planetTransFre": "Mars" }, { "planetTransIta": "Marte" } ] } ]
数据类代码
@Serializable @Entity(tableName = "Planets") data class PlanetItem( @PrimaryKey val planetId: String, @ColumnInfo val planetName: String, @ColumnInfo val planetTransSpa: String, @ColumnInfo val planetTransFre: String, @ColumnInfo val planetTransIta: String )
Jetpack Compose中无效代码
Text( text = uiState?.planetTransSpa?: "" )
问题核心
你的JSON里planetTranslations是一个包含多个单字段对象的数组,但数据类PlanetItem直接将翻译字段作为自身属性,序列化器无法将数组中的分散对象映射到单个对象的属性上,导致解析后翻译字段为空,Compose无法正常显示内容。
解决方法
方法一:调整数据类结构适配嵌套数组
先定义翻译项的数据类:
@Serializable data class PlanetTranslation( val planetTransSpa: String? = null, val planetTransFre: String? = null, val planetTransIta: String? = null )
修改PlanetItem的结构:
@Serializable @Entity(tableName = "Planets") data class PlanetItem( @PrimaryKey val planetId: String, @ColumnInfo val planetName: String, val planetTranslations: List<PlanetTranslation> )
由于Room不支持直接存储List,需要添加类型转换器:
class Converters { @TypeConverter fun fromTranslationList(list: List<PlanetTranslation>): String { return Json.encodeToString(list) } @TypeConverter fun toTranslationList(json: String): List<PlanetTranslation> { return Json.decodeFromString(json) } }
在Room数据库类上添加注解启用转换器:
@Database(entities = [PlanetItem::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun planetDao(): PlanetDao }
之后在Compose中提取对应翻译内容:
// 获取西班牙语翻译 val spaTrans = uiState?.planetTranslations?.firstOrNull { it.planetTransSpa != null }?.planetTransSpa ?: "" Text(text = spaTrans)
方法二:自定义序列化器扁平嵌套字段
编写自定义序列化器,自动将数组中的翻译字段提取到根对象:
object PlanetItemSerializer : JsonTransformingSerializer<PlanetItem>(Json.serializersModule.serializer()) { override fun transformDeserialize(element: JsonElement): JsonElement { val root = element.jsonObject val translationsArray = root["planetTranslations"]?.jsonArray ?: JsonArray(emptyList()) return buildJsonObject { // 复制原有字段 root.forEach { (key, value) -> if (key != "planetTranslations") put(key, value) } // 提取数组中的翻译字段 translationsArray.forEach { transObj -> transObj.jsonObject.forEach { (key, value) -> put(key, value) } } } } }
修改PlanetItem的序列化注解:
@Serializable(with = PlanetItemSerializer::class) @Entity(tableName = "Planets") data class PlanetItem( @PrimaryKey val planetId: String, @ColumnInfo val planetName: String, @ColumnInfo val planetTransSpa: String, @ColumnInfo val planetTransFre: String, @ColumnInfo val planetTransIta: String )
这样解析后,你的原Compose代码就能正常显示翻译内容了。
内容的提问来源于stack exchange,提问作者Mister Propre
相关产品推荐
相关产品推荐

