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

Android Kotlin中Moshi PolymorphicJsonAdapter无法运行报错问题

Moshi多态JSON解析失效排查方案

问题根因

你看到的Accessing hidden method Ljava/lang/invoke/MethodHandles$Lookup;->(Ljava/lang/Class;I)V只是Android 9+系统输出的隐藏API反射告警,不是导致解析失败的核心原因,真正的问题出在三处配置错误:

  • 多态标签值不匹配:你给枚举字段加的@Json(name = "MediaTile")注解仅在Moshi序列化/反序列化枚举本身时生效,调用TileContentType.mediaTile.name取到的是枚举常量的原生名称mediaTile(首字母小写),和接口返回的type字段值MediaTile(首字母大写)完全不一致,多态适配器无法匹配到对应子类,直接触发解析失败。
  • 基类字段重复定义:Tile基类构造函数里已经声明了type和id字段,子类MediaTile又重写了这两个字段,会导致Moshi解析时重复映射字段,出现赋值异常。
  • 低版本Moshi兼容问题:1.13以下版本的Moshi使用了Android高版本限制访问的隐藏反射API,会持续输出你看到的告警日志,部分机型上甚至会直接触发反射失败。

修复步骤

1. 修正多态标签值传参

不要直接取枚举的name属性,给枚举增加自定义字段存储和接口一致的标签值:

enum class TileContentType(val label: String) {
    MEDIA_TILE("MediaTile"),
    QUESTION_TILE("QuestionTile"),
    CONVERSATION_STARTER_TILE("ConversationStarterTile")
}

Moshi实例配置保持官方推荐的顺序即可(KotlinJsonAdapterFactory放在最后作为兜底适配器),修改标签传参:

@Provides
fun provideRetrofit(okHttpClient: OkHttpClient, BASE_URL: String): Retrofit {
    val moshi = Moshi.Builder()
        .add(
            PolymorphicJsonAdapterFactory.of(Tile::class.java, "type")
                .withSubtype(MediaTile::class.java, TileContentType.MEDIA_TILE.label)
                .withSubtype(QuestionTile::class.java, TileContentType.QUESTION_TILE.label)
                .withSubtype(ConversationStarterTile::class.java, TileContentType.CONVERSATION_STARTER_TILE.label)
        )
        // Kotlin反射适配器放在最后注册,兜底处理所有没有自定义适配器的类
        .add(KotlinJsonAdapterFactory())
        .build()
    return Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .client(okHttpClient)
        .build()
}

2. 重构基类避免字段重复

将Tile改为密封类,去掉构造函数的传参,所有字段由子类实现,从根源避免重复映射:

sealed class Tile {
    @Json(name = "type")
    abstract val type: String
    @Json(name = "id")
    abstract val id: String
}

对应修改MediaTile的继承逻辑,去掉父类构造传参:

data class MediaTile(
    @Json(name= "id") override val id: String,
    @Json(name= "type") override val type: String,
    override val author: Author,
    override val createdDate: String,
    override var text: PostText?,
    override val topComment: Comment?,
    override val seeAllCommentsAction: DeeplinkAction?,
    override val allComments: List<Comment?>?,
    override val tags: List<Tag>?,
    val images: List<TileImage>?,
    val reactions: PostReactions?,
) : Tile(), PostTile

3. 升级Moshi依赖消除反射告警

将Moshi相关依赖升级到1.14.0及以上稳定版本,官方已经适配了Android高版本的隐藏API限制,升级后不会再出现相关告警日志,也不会触发反射失败。

验证方法

改完配置后先写本地单元测试验证逻辑,不需要发起真实接口请求:

@Test
fun testPolymorphicParse() {
    val moshi = Moshi.Builder()
        .add(
            PolymorphicJsonAdapterFactory.of(Tile::class.java, "type")
                .withSubtype(MediaTile::class.java, "MediaTile")
        )
        .add(KotlinJsonAdapterFactory())
        .build()
    val adapter = moshi.adapter(Tile::class.java)
    // 填充接口返回的最小必要字段
    val testJson = """
        {"type":"MediaTile","id":"001","author":{},"createdDate":"2024-01-01"}
    """.trimIndent()
    val result = adapter.fromJson(testJson)
    // 验证解析结果类型正确
    check(result is MediaTile)
}

内容的提问来源于stack exchange,提问作者Jalson1982

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:12:25