【问题标题】:Moshi's Custom Adapter with RxAndroid & Retrofit & KotlinMoshi 的 RxAndroid & Retrofit & Kotlin 的自定义适配器
【发布时间】:2017-03-18 13:28:45
【问题描述】:

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

{ “消息”:“成功”, “用户”:{ “用户名”:“埃里克” } }

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

类用户(var 用户名:字符串) 类 UserJson(var 消息:字符串,var 用户:用户)

还有一个用于 Moshi 的自定义类型适配器:

类用户适配器 { @FromJson fun fromJson(userJson: UserJson) : User { Log.d("MyLog", "message = ${userJson.message}") // = 成功 Log.d("MyLog", "user = ${userJson.user}") // = null 返回用户Json.user } }

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

我是 Moshi 和 Kotlin 的新手,我已经在这个问题上坚持了大约 10 个小时。请帮帮我。感谢您的帮助。

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

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

类 MainActivity : AppCompatActivity() { 覆盖 fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Moshi 的自定义类型适配器 val userMoshi = Moshi.Builder().add(UserAdapter()).build() val 改造 = Retrofit.Builder() .baseUrl("https://dl.dropboxusercontent.com/") .addConverterFactory(MoshiConverterFactory.create(userMoshi)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 。建造() val accountService = retrofit.create(AccountService::class.java) accountService.signUpAnonymously() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { 用户 -> Log.d("MyLog", user.toString()) } } } // ========== 用于改造 ========== 接口帐户服务{ @GET("u/17350105/test.json") 有趣的 signUpAnonymously() : Observable } // ========== 对于 Moshi ========== 类用户(var 用户名:字符串) 类 UserJson(var 消息:字符串,var 用户:用户) 类用户适配器 { @FromJson fun fromJson(userJson: UserJson) : User { Log.d("MyLog", "message = ${userJson.message}") // = 成功 Log.d("MyLog", "user = ${userJson.user}") // = null 返回用户Json.user } }

build.gradle 是:

编译“io.reactivex.rxjava2:rxjava:2.0.0” 编译“io.reactivex.rxjava2:rxandroid:2.0.0” 编译“com.android.support:appcompat-v7:25.0.0” 编译“com.squareup.retrofit2:retrofit:2.1.0” 编译“com.squareup.retrofit2:converter-moshi:2.1.0” 编译'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

再次感谢您。

【问题讨论】:

    标签: android rx-java kotlin retrofit2 moshi


    【解决方案1】:

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

    基本上,在您注册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)
        }
    }
    

    【讨论】:

    • 它有效,谢谢!我还有一个问题:有没有更好的方法来实现相同的目标? (我唯一需要做的就是从原始 JSON 中获取 user 字段。)
    【解决方案2】:

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

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

    不需要任何其他自定义适配器。

    【讨论】:

    • 刚刚在 Moshi 的 GitHub 页面 (#182 #176 #113) 看到了一些相关问题。非常感谢您的 Moshi-Lazy-Adapters!
    • 为了补充答案,您应该在改造建设者。如果你需要更深的路径 "@Wrapped(path = ["a", "b", "c"])"
    猜你喜欢
    • 2017-03-09
    • 2017-02-08
    • 2018-06-17
    • 2019-04-04
    • 2019-01-04
    • 1970-01-01
    • 2021-04-01
    • 2020-02-02
    • 1970-01-01
    相关资源
    最近更新 更多