You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:50:06