我正在尝试使用 Ktor 和 Kotlinx 序列化从 jsonplaceholder.typicode.com ( here ) 中提取一些虚拟帖子数据并反序列化数组。但是,我收到以下错误:
Error:Expected class kotlinx.serialization.json.JsonObject (Kotlin reflection is not available) as the serialized body of kotlinx.serialization.Polymorphic<List>, but had class kotlinx.serialization.json.JsonArray (Kotlin reflection is not available)
我在代码中的哪个位置指定我期望数据为 JsonObjects 而不是 JsonArrays?这可能是错误,但我没有看到我在代码中指定的位置。
预先感谢您的帮助。
相关代码贴在这里:
LoginRegisterFragment.kt
package com.example.groupupandroid
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController
import com.example.groupupandroid.databinding.ActivityMainBinding
import com.example.groupupandroid.databinding.FragmentLoginRegisterBinding
import data.remote.PostResponse
import data.remote.PostsService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
class LoginRegisterFragment : Fragment(){
// Getting xml objects
private var binding: FragmentLoginRegisterBinding? = null
// Creating service for networking
private lateinit var service: PostsService
private var posts: List<PostResponse> = emptyList()
//@Composable
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentLoginRegisterBinding.inflate(layoutInflater)
lifecycleScope.launch {getPosts()}
// Inflate the layout for this fragment
return binding?.root
}
private suspend fun getPosts() {
service = PostsService.create()
posts = service.getPosts()
print(posts)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// If register button is tapped make register visible
binding?.registerToggleButton?.setOnClickListener {
binding?.registerFields?.visibility = View.VISIBLE
binding?.loginFields?.visibility = View.GONE
}
// If login button is tapped make login visible
binding?.loginToggleButton?.setOnClickListener {
binding?.registerFields?.visibility = View.GONE
binding?.loginFields?.visibility = View.VISIBLE
}
// If login button is pushed swap to maps
binding?.loginButton?.setOnClickListener {
findNavController().navigate(R.id.loginToHomeScreen)
}
// If register button is pushed swap to maps
binding?.registerButton?.setOnClickListener {
findNavController().navigate(R.id.loginToHomeScreen)
}
binding?.materialButtonToggleGroup?.check(binding?.loginToggleButton!!.id)
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
PostResponse.kt
package data.remote
import kotlinx.serialization.Serializable
@Serializable
data class PostResponse (
val body: String,
val title: String,
val id: Int,
val userId: Int
)
PostsServiceImplementation.kt
package data.remote
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.util.*
import java.lang.Exception
class PostsServiceImplementation(private val client: HttpClient): PostsService
{
override suspend fun getPosts(): List<PostResponse> {
return try {
client.get {url(HttpRoutes.POSTS)}.body()
} catch(e: Exception){
println("Error:${e.message}")
emptyList()
}
}
override suspend fun createPosts(postRequest: PostRequest): PostResponse? {
return try {
client.post {
url(HttpRoutes.POSTS)
contentType(ContentType.Application.Json)
setBody(postRequest)
}.body()
} catch(e: Exception) {
println("Error:${e.message}")
null
}
}
}
编辑:更多相关代码。
HttpRoutes.kt
package data.remote
object HttpRoutes {
private const val BASE_URL = "https://jsonplaceholder.typicode.com"
const val POSTS = "$BASE_URL/posts"
}
PostsService.kt
package data.remote
import io.ktor.client.*
import io.ktor.client.engine.android.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.kotlinx.serializer.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.statement.*
import io.ktor.serialization.kotlinx.json.*
interface PostsService {
suspend fun getPosts(): List<PostResponse>
suspend fun createPosts(postRequest: PostRequest): PostResponse?
companion object {
fun create():PostsService {
return PostsServiceImplementation (
client = HttpClient(Android) {
install(Logging) {
level = LogLevel.ALL
}
install(ContentNegotiation) {
json()
}
}
)
}
}
}
PostRequest.kt
package data.remote
import kotlinx.serialization.Serializable
@Serializable
data class PostRequest (
val body: String,
val title: String,
val userId: Int
)
最佳答案
我要结束这个问题了。发现我的数据类上显示以下消息:“kotlinx.serialization 编译器插件未应用于该模块,因此不会处理此注释。请确保您已正确设置构建脚本并重新导入项目”。问题是我没有在我的 build.gradle.kts (应用程序)中包含以下行
kotlin("plugin.serialization") version "1.7.10"
我也使用了 ProGuard,但没有包含对 ProGuard 规则的相关更改(请参阅 here )。
关于android - 使用 Ktor 反序列化 Json 数组的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73171936/