Moshi 的自定义适配器与 RxAndroid & Retrofit & Kotlin
Moshi's Custom Adapter with RxAndroid & Retrofit & Kotlin
为Android项目配置Kotlin后,写了一个简单的MainActivity.kt
。它调用 Retrofit 获取一个 JSON 文件,其中包含以下数据:
{
"message": "success",
"user":{
"username": "Eric"
}
}
现在我想用Moshi将JSON数据转换成Kotlin的class,所以这里有两个classes来反映上面的JSON结构:
class 用户(var 用户名:字符串)
class UserJson(var message: String, var user: User)
以及 Moshi 的自定义类型适配器:
class 用户适配器{
@FromJson 有趣 fromJson(userJson: UserJson) : 用户 {
Log.d("MyLog", "message = ${userJson.message}") // = 成功
Log.d("MyLog", "user = ${userJson.user}") // = 空
return userJson.user
}
}
当它按预期进入函数 fromJson()
、userJson.message = "success"
时。但是奇怪的是userJson.user
是null
,应该是User(username="Eric")
.
我是 Moshi 和 Kotlin 的新手,我已经为这个问题坚持了大约 10 个小时。请帮帮我。感谢您的帮助。
========================================
以下是MainActivity.kt
的全部代码(仅50行):
class MainActivity : AppCompatActivity() {
重写乐趣 onCreate(savedInstanceState: Bundle?) {
super.onCreate(已保存实例状态)
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 ==========
class 用户(var 用户名:字符串)
class UserJson(var message: String, var user: User)
class 用户适配器{
@FromJson 有趣 fromJson(userJson: UserJson) : 用户 {
Log.d("MyLog", "message = ${userJson.message}") // = 成功
Log.d("MyLog", "user = ${userJson.user}") // = 空
return userJson.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'
再次感谢。
您可以通过更改代码执行如下操作来解决问题。
基本上在您注册 UserAdapter
的情况下,它告诉 moshi 它只能从 UserJson
对象创建 User
。因此 Moshi 无法识别关键字为 user
.
的 JSON 对象
通过添加 User1
形式的间接寻址(请原谅命名约定),UserJson
可以使用 JSON.[=18] 中的 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)
}
}
如果您只需要 User
对象。有一个名为 Moshi-Lazy-Adapters 的库提供了 @Wrapped
注释,允许指定所需对象的路径。您所要做的就是将相应的适配器添加到您的 Moshi 实例并将服务代码更改为:
interface AccountService {
@GET("u/17350105/test.json")
@Wrapped("user")
fun signUpAnonymously() : Observable<User>
}
不需要任何其他自定义适配器。
为Android项目配置Kotlin后,写了一个简单的MainActivity.kt
。它调用 Retrofit 获取一个 JSON 文件,其中包含以下数据:
{ "message": "success", "user":{ "username": "Eric" } }
现在我想用Moshi将JSON数据转换成Kotlin的class,所以这里有两个classes来反映上面的JSON结构:
class 用户(var 用户名:字符串) class UserJson(var message: String, var user: User)
以及 Moshi 的自定义类型适配器:
class 用户适配器{ @FromJson 有趣 fromJson(userJson: UserJson) : 用户 { Log.d("MyLog", "message = ${userJson.message}") // = 成功 Log.d("MyLog", "user = ${userJson.user}") // = 空 return userJson.user } }
当它按预期进入函数 fromJson()
、userJson.message = "success"
时。但是奇怪的是userJson.user
是null
,应该是User(username="Eric")
.
我是 Moshi 和 Kotlin 的新手,我已经为这个问题坚持了大约 10 个小时。请帮帮我。感谢您的帮助。
========================================
以下是MainActivity.kt
的全部代码(仅50行):
class MainActivity : AppCompatActivity() { 重写乐趣 onCreate(savedInstanceState: Bundle?) { super.onCreate(已保存实例状态) 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 ========== class 用户(var 用户名:字符串) class UserJson(var message: String, var user: User) class 用户适配器{ @FromJson 有趣 fromJson(userJson: UserJson) : 用户 { Log.d("MyLog", "message = ${userJson.message}") // = 成功 Log.d("MyLog", "user = ${userJson.user}") // = 空 return userJson.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'
再次感谢。
您可以通过更改代码执行如下操作来解决问题。
基本上在您注册 UserAdapter
的情况下,它告诉 moshi 它只能从 UserJson
对象创建 User
。因此 Moshi 无法识别关键字为 user
.
通过添加 User1
形式的间接寻址(请原谅命名约定),UserJson
可以使用 JSON.[=18] 中的 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)
}
}
如果您只需要 User
对象。有一个名为 Moshi-Lazy-Adapters 的库提供了 @Wrapped
注释,允许指定所需对象的路径。您所要做的就是将相应的适配器添加到您的 Moshi 实例并将服务代码更改为:
interface AccountService {
@GET("u/17350105/test.json")
@Wrapped("user")
fun signUpAnonymously() : Observable<User>
}
不需要任何其他自定义适配器。