【问题标题】:android kotlin retrofit2 com.google.gson.JsonSyntaxException Expected string but was BEGIN_OBJECT [duplicate]android kotlin retrofit2 com.google.gson.JsonSyntaxException 预期的字符串,但为 BEGIN_OBJECT [重复]
【发布时间】:2021-09-22 14:54:36
【问题描述】:

我正在开发一个 Kotlin 应用程序,它连接了一个使用 Retrofit 2 的测试 API。

一切都很好,直到我尝试实现一个查询,让用户通过 id 过滤对 API 的调用。

所以我得到了上面的标题错误

关于我的课程如下:

MainActivity.kt


@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding


    private lateinit var id: Number
    private val quoteViewModel: QuoteViewModel by viewModels()
    private lateinit var userSearch: QuoteModel;
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //Pasa el layout a linkear con el binding.
        binding = ActivityMainBinding.inflate(layoutInflater)

        //settemos la vista
        setContentView(binding.root)

        var Etid: EditText = findViewById(R.id.EtId)
        //Inicializamos el controlador UI-data (ViewModel)
        quoteViewModel.onCreate()

        //Establecemos un observer en los datos
        quoteViewModel.quoteModel.observe(this, Observer {
            binding.tvName.text = it.name
            binding.tvEmail.text = it.email
            binding.tvAddress.text = it.addrees
            binding.tvPhone.text = it.phone
            binding.tvWebsite.text = it.website
            binding.tvCompany.text = it.company
        })
        //Establecemos un observer en la carga de la página.
        quoteViewModel.isLoading.observe(this, Observer {
            binding.loading.isVisible = it
        })


    //No uso el binding porque fallaba el Dagger (Inyector de dependencias)

        binding.viewContainer.setOnClickListener {
            id = Etid.id;
            userSearch = quoteViewModel.getUserIdQuote(id as Int) as QuoteModel
            it.findViewById<TextView>(R.id.tvName).text = userSearch.name
            it.findViewById<TextView>(R.id.tvAddress).text  = userSearch.addrees
            it.findViewById<TextView>(R.id.tvCompany).text = userSearch.company
            it.findViewById<TextView>(R.id.tvEmail).text = userSearch.email
            it.findViewById<TextView>(R.id.tvPhone).text = userSearch.phone
            it.findViewById<TextView>(R.id.tvWebsite).text = userSearch.website
        }

    }

}

QuoteService.kt

@Singleton
class QuoteService @Inject constructor(private val api:QuoteApiClient) {
    suspend fun getAllUsers(): List<QuoteModel> {
        return withContext(Dispatchers.IO) {
            val response = api.getAllUUsers()
            response.body() ?: emptyList1()
        }
    }

    suspend fun getUserById(id:Number): QuoteModel{
        return withContext(Dispatchers.IO){
            val response = api.getUserById(id)
            response.body() ?: listOf<QuoteModel>()
        } as QuoteModel
    }
}

QuoteProvider.kt


@Singleton
class QuoteProvider @Inject constructor() {
    var allUsers: List<QuoteModel> = emptyList1()
    var userById: QuoteModel? = null

}

QuoteRepository.kt

class QuoteRepository @Inject constructor(
    private val api: QuoteService,
    private val quoteProvider: QuoteProvider
) {

    suspend fun getAllUsers(): List<QuoteModel> {
        //extraemos los users de la api
        val response = api.getAllUsers()
            //Le pasamos el [] de users al repository de la app.
        quoteProvider.allUsers = response
        return response
    }

    suspend fun getUserById(id: Number): QuoteModel {
        //Recogemos el usuario pasandole el Id al QueryRepository
        val response = api.getUserById(id)
        quoteProvider.userById = response

        return response
    }
}

关于我调用 pull 的类,如下。

GetAllUsers.kt

class GetAllUsers @Inject constructor(private val repository: QuoteRepository) {
    suspend operator fun invoke() = repository.getAllUsers()

}

GetUsersById.kt

class GetUserById @Inject constructor(private val provider: QuoteProvider) {

    //TODO() Si no funciona probar a sacarlo del repository.
    suspend  operator fun invoke(id: kotlin.Int): QuoteModel? {
        //val id = id
        return provider.userById
    }
}

最后是我的 ViewModel:

QuoteViewModel.kt

@HiltViewModel
class QuoteViewModel @Inject constructor(
    private val getAllUsers:GetAllUsers,
    private val getUserById: GetUserById
) : ViewModel() {

    val quoteModel = MutableLiveData<QuoteModel>()
    val isLoading = MutableLiveData<Boolean>()

    fun onCreate() {
        viewModelScope.launch {
            isLoading.postValue(true)
            val result = getAllUsers()

            if(!result.isNullOrEmpty()){
                quoteModel.postValue(result[0])
                isLoading.postValue(false)
            }
        }
    }

    fun getUserIdQuote(id: Int) {
        viewModelScope.launch {
            isLoading.postValue(true)
            val quote = getUserById(id)
            if (quote != null) {
                quoteModel.postValue(quote)
            }
            isLoading.postValue(false)
        }
    }
}

[编辑]

添加了改造网络连接:

QuoteApiClient.kt

interface QuoteApiClient {
    @GET("/users")
    suspend fun getAllUUsers(): Response<List<QuoteModel>>

    @GET("/users/?{id}")
    suspend fun getUserById(id: Number): Response<QuoteModel>

}

我的 QuoteModel.kt 类

data class QuoteModel(
    @SerializedName("id") val quote: Number,
    @SerializedName("name") val name: String,
    @SerializedName("email") val email: String,
    @SerializedName("address") val addrees: String,
    @SerializedName("phone") val phone: String,
    @SerializedName("website") val website: String,
    @SerializedName("company") val company: String,
    ) {


}

https://jsonplaceholder.typicode.com/users 的 json 响应返回一个对象数组,如下所示:

[
    {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
            "street": "Kulas Light",
            "suite": "Apt. 556",
            "city": "Gwenborough",
            "zipcode": "92998-3874",
            "geo": {
                "lat": "-37.3159",
                "lng": "81.1496"
            }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
            "name": "Romaguera-Crona",
            "catchPhrase": "Multi-layered client-server neural-net",
            "bs": "harness real-time e-markets"
        }
    },

我希望你知道这种错误是如何指代的,这显然与我连接 API 时操作数据的方式有关。

因此,如果您能提供帮助,请提前接受!

【问题讨论】:

  • 您的问题是关于改造,但您没有显示任何改造实现或从 api 返回的 json
  • 感谢您的评论!我已经添加了
  • 而你的报价模型类,你拥有的所有其他代码都是不必要的
  • 已经添加了。虽然我已经在第一次编辑时添加了,抱歉。

标签: android kotlin retrofit2


【解决方案1】:

在您的数据对象 QuoteModel 中,您将地址作为字符串值

@SerializedName("address") val addrees: String

和公司作为字符串值

@SerializedName("company") val company: String

你的 Json 这些值是对象

地址对象

"address": {
        "street": "Kulas Light",
        "suite": "Apt. 556",
        "city": "Gwenborough",
        "zipcode": "92998-3874",
        "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
        }
    }

公司对象

"company": {
        "name": "Romaguera-Crona",
        "catchPhrase": "Multi-layered client-server neural-net",
        "bs": "harness real-time e-markets"
    }

您需要为您的数据类创建地址和公司对象

【讨论】:

    猜你喜欢
    • 2016-08-20
    • 1970-01-01
    • 2015-11-06
    • 2014-08-02
    • 2019-05-10
    • 2020-01-29
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多