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

Android AWS DynamoDB使用Moshi时mapper.save报错求助

Moshi与AWS DynamoDB配合时字段映射失效的解决方案

问题背景

使用AWS DynamoDB存储CommunityUser对象,此前用Gson的@SerializedName实现类属性与JSON字段的映射,切换到Moshi的@Json注解后,调用DynamoDBMapper.save时崩溃,报错信息:

Null or empty value for key: public final java.lang.String core.model.CommunityUser.getUserId()

涉及代码

CommunityUser类(Moshi注解版本)

class CommunityUser {
    @get:DynamoDBHashKey(attributeName = AWSTables.TableCommunityUser.user_id)
    @Json(name = "user_id")
    var userId: String = ""

    @get:DynamoDBAttribute(attributeName = AWSTables.TableCommunityUser.email)
    @Json(name = "email")
    var email: String = ""

    @get:DynamoDBAttribute(attributeName = AWSTables.TableCommunityUser.user)
    @Json(name = "user")
    var alias: String = ""

    @get:DynamoDBAttribute(attributeName = AWSTables.TableCommunityUser.pass)
    @Json(name = "pass")
    var password: String = ""

    @get:DynamoDBAttribute(attributeName = AWSTables.TableCommunityUser.picture)
    @Json(name = "picture")
    var picture: String = ""
}

更新用户的核心代码

override fun updateUser(jsonUser: String): CommunityUserDTO? {
    val user: CommunityUser?
    var userDTO: CommunityUserDTO? = null
    val dynamoDBMapperConfig = AWSConnection.mapperConfig4Update
    try {
        user = AWSHelper.deserializeUser(jsonUser)
        AWSTestRepository.awsConnection.mapper.save(user, dynamoDBMapperConfig)
        userDTO = jsonUser.deserialize<CommunityUserDTO>()
    } catch (e: Exception) {
        e.logException()
    }
    return userDTO
}

AWS连接与Mapper初始化代码

class AWSConnection {
    lateinit var mapper: DynamoDBMapper
        private set
    lateinit var ddbClient: AmazonDynamoDBClient
        private set

    companion object {
        private lateinit var poolId: String
        private val databaseRegion = Regions.xxx
        @JvmStatic
        val mapperConfig4Update: DynamoDBMapperConfig
            get() = DynamoDBMapperConfig.Builder()
                .withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)
                .withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.UPDATE)
                .build()

        private fun initializeAWSIdentityPoolDynamoDBMapper(context: Context): DynamoDBMapper {
            val credentialsProvider = CognitoCachingCredentialsProvider(
                context,
                poolId,
                databaseRegion
            )
            val ddbClient = com.amazonaws.regions.Region.getRegion(databaseRegion)
                .createClient(
                    AmazonDynamoDBClient::class.java,
                    credentialsProvider,
                    ClientConfiguration()
                )
            return DynamoDBMapper.builder().dynamoDBClient(ddbClient).build()
        }

        private fun initializeAWSIdentityPoolAmazonDynamoDBClient(context: Context): AmazonDynamoDBClient {
            val credentialsProvider = CognitoCachingCredentialsProvider(
                context,
                poolId,
                databaseRegion
            )
            return com.amazonaws.regions.Region.getRegion(databaseRegion)
                .createClient(
                    AmazonDynamoDBClient::class.java,
                    credentialsProvider,
                    ClientConfiguration()
                )
        }
    }
}

解决方案

1. 明确注解职责,分离映射逻辑

DynamoDB的注解(@DynamoDBHashKey、@DynamoDBAttribute)仅负责对象与DynamoDB表字段的映射,Moshi的@Json注解仅负责JSON与对象的序列化/反序列化,两者互不干扰,无需修改DynamoDB的配置适配Moshi。

2. 确保Moshi实例正确配置

Kotlin项目必须添加moshi-kotlin依赖,并在创建Moshi实例时加入KotlinJsonAdapterFactory,否则Kotlin类的注解可能无法生效:

// 正确初始化Moshi实例
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

// 修正deserializeUser方法
fun deserializeUser(json: String): CommunityUser? {
    val adapter = moshi.adapter(CommunityUser::class.java)
    return adapter.fromJson(json)
}

3. 验证反序列化结果

在调用dynamoDBMapper.save前,检查user对象的userId值是否为空:

user = AWSHelper.deserializeUser(jsonUser)
// 调试或打印验证userId
if (user?.userId.isNullOrEmpty()) {
    throw IllegalArgumentException("JSON中缺少user_id字段或值为空")
}
AWSTestRepository.awsConnection.mapper.save(user, dynamoDBMapperConfig)

4. 检查JSON输入合法性

确认传入的jsonUser字符串中包含非空的user_id字段,例如:

{
    "user_id": "12345",
    "email": "user@example.com",
    "user": "test_alias",
    "pass": "password123",
    "picture": "avatar_url"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:15:59