首页 文章

Moshi的定制适配器,带有RxAndroid和Retrofit&Kotlin

提问于
浏览
3

在为Android项目配置Kotlin之后,我写了一个简单的 MainActivity.kt . 它调用Retrofit来获取包含以下数据的JSON文件:

{
    "message": "success",
    "user": {
        "username": "Eric"
    }
}

现在我想使用Moshi将JSON数据转换为Kotlin的类,所以这里有两个类来反映上面的JSON结构:

class User(var username: String)

class UserJson(var message: String, var user: User)

和Moshi的自定义类型适配器:

class UserAdapter {
    @FromJson fun fromJson(userJson: UserJson) : User {
        Log.d("MyLog", "message = ${userJson.message}")  // = success
        Log.d("MyLog", "user = ${userJson.user}")        // = null

        return userJson.user
    }
}

当它按预期进入函数 fromJson()userJson.message = "success" 时 . 但奇怪的是 userJson.usernull ,应该是 User(username="Eric") .

我是Moshi和Kotlin的新手,我已经坚持了这个问题大约10个小时 . 请帮帮我 . 谢谢你的帮助 .

========================================

以下是 MainActivity.kt 的整个代码(仅限50行):

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Custom Type Adapters for Moshi
        val userMoshi = Moshi.Builder().add(UserAdapter()).build()

        val retrofit = Retrofit.Builder()
                .baseUrl("https://dl.dropboxusercontent.com/")
                .addConverterFactory(MoshiConverterFactory.create(userMoshi))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()

        val accountService = retrofit.create(AccountService::class.java)

        accountService.signUpAnonymously()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { user ->
                    Log.d("MyLog", user.toString())
                }
    }
}


// ========== For Retrofit ==========
interface AccountService {

    @GET("u/17350105/test.json")
    fun signUpAnonymously() : Observable<User>

}


// ========== For Moshi ==========
class User(var username: String)

class UserJson(var message: String, var user: User)

class UserAdapter {

    @FromJson fun fromJson(userJson: UserJson) : User {
        Log.d("MyLog", "message = ${userJson.message}")        // = success
        Log.d("MyLog", "user = ${userJson.user}")              // = null

        return userJson.user
    }

}

build.gradle 是:

compile "io.reactivex.rxjava2:rxjava:2.0.0"
compile "io.reactivex.rxjava2:rxandroid:2.0.0"

compile "com.android.support:appcompat-v7:25.0.0"

compile "com.squareup.retrofit2:retrofit:2.1.0"
compile "com.squareup.retrofit2:converter-moshi:2.1.0"
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

再次感谢你 .

2 回答

  • 2

    您可以通过更改代码来执行以下操作来解决问题 .

    基本上在你注册 UserAdapter 的情况下,它告诉moshi它只能从 UserJson 对象创建一个 User . 因此,Moshi无法使用关键字 user 识别JSON对象 .

    通过以 User1 的形式添加间接(请原谅命名约定), UserJson 是使用JSON的 User1 正确创建的 .

    class User(var username: String)
    
    class User1(var username: String) // I introduced this class
    class UserJson(var message: String, var user: User1) // changed User to User1
    
    class UserAdapter {
        @FromJson fun fromJson(userJson: UserJson): User {
            println("message = ${userJson.message}")        
            println("user = ${userJson.user}")              
            return User(userJson.user.username)
        }
    }
    
  • 3

    如果你只需要 User 对象 . 有一个名为Moshi-Lazy-Adapters的库提供 @Wrapped 注释,允许指定所需对象的路径 . 您所要做的就是将相应的适配器添加到您的moshi实例中,并将服务代码更改为:

    interface AccountService {
    
      @GET("u/17350105/test.json")
      @Wrapped("user")
      fun signUpAnonymously() : Observable<User>
    }
    

    无需任何其他自定义适配器 .

相关问题