当前位置: 首页 > 知识库问答 >
问题:

Moshi的自定义适配器与RxAndroid&Reverfit&Kotlin

陈浩
2023-03-14

在为Android项目配置Kotlin之后,我编写了一个简单的mainactivity.kt。它调用了reverfit来获得一个包含以下数据的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”)

我对莫希和科特林是新的,我已经在这个问题上坚持了大约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'

再次谢谢你。

共有1个答案

衡高寒
2023-03-14

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

基本上,在您的例子中,当useradapter注册时,它告诉moshi它只能从userjson对象创建user。因此,Moshi无法识别具有关键字user的JSON对象。

通过添加user1形式的间接(请原谅命名约定),可以使用来自JSON的user1正确创建userJSON

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)
    }
}
 类似资料:
  • 我在我的应用程序中使用了reverfit(V2.9.0)和Moshi(V1.11.0)。我尝试这样调用endpoint: 但是WatchStatus->JSON转换没有像预期的那样工作。WatchStatus是一个简单的枚举类: 我创建了一个自定义适配器,因为我的应用程序使用大写枚举名称,而后端使用小写名称: 我以以下方式创建Moshi实例: 并且我的改型实例使用它(带有Koin注入): 解析Js

  • 我使用一个API,它以数组的形式返回数据,比如这个JSON字符串(我们称之为“任务”) 我想将这个响应解析为一个列表。所以我已经用生成的适配器创建了相应的数据类 我的改装服务是这样的 但我想使用容器类型,例如: 作为网络响应结果。这可能不创建自定义adpter或者我将需要创建一个自定义适配器并将其传递给moshi构建器吗?

  • 好了,我有了以下Json POJO: > 基于JProduct内部的某些值 JCategory two列表将合并为1,其中将包含更多的JCategory加上prod1/prod2。 根据Moshi的说法,这是映射适配器中数据的有效和高效的方法吗? 注意,我有一个JCategory,并且在同一个对象的列表中,所以我认为适配器会自动解析它,但它没有。所以我尝试了并成功了。 所以我的问题是: 是处理这种

  • 英文原文:http://emberjs.com/guides/models/customizing-adapters/ 在Ember Data中,处理与后台数据仓库通信的逻辑是通过Adapter来完成的。Ember Data适配器内置了一些关于REST API的假定。如果后台的实现与Ember Data假定的惯例不同,那么通过扩展缺省的适配器可能很容易的实现。 有时因为一些原因需要自定义适配器,例

  • Ember.js适配器指定如何在后端数据存储中保存数据,例如URL格式和REST API标头。 默认的Ember适配器包含一些REST API的内置假设。 这些假设有助于更轻松,更好地构建Web应用程序。 可以使用以下命令创建适配器 - ember generate adapter adapter-name 运行上面的命令时,它将显示以下行 - import DS from 'ember-dat

  • 问题内容: 下面的示例显示了一个类(Club),其中包含抽象类(成员)的集合。我对于是否需要TypeAdapter或JsonDeserializer才能使反序列化正常工作感到困惑。序列化在没有任何帮助的情况下就可以正常工作,但是反序列化会引发异常。为了说明这一点,我构建了以下“克隆”测试。如果有人能展示一个有效的例子,我将不胜感激。 头等舱 现在是抽象基类成员 以及成员的两个具体子类(金和银​​)