我的 API 返回 null 或帖子列表。帖子的数据类如下所示
@Serializable
data class Post(
val id: Int,
val text: String,
@SerialName("img_url") val imgURL: String,
var author: User
)
@Serializable
data class User(
val id: Int,
@SerialName("profile_img") val profileImgUrl: String,
@SerialName("user_name") val userName: String
)
我还有一个如下的API接口
interface PosterApiInterface {
@GET("posts")
suspend fun getPosts(
@Query("start") lastPostId: Int,
@Query("limit") posts: Int,
@Query("username") username: String? = null
): List<Post>?
// There's also code that relates to security components and other functionality,
// but I've decided to hide it
}
但我看到仅仅使
List<Post>
可为空是不够的,因为转换器工厂仍然返回此错误:
io.github.xn32.json5k.UnexpectedValueError: array expected at position 1:1
每次服务器发送空值。这是我的改造:
private val baseUrl = "https://127.0.0.1:3001/" // Poster API
private val json = Json5 { prettyPrint = true; }
@OptIn(ExperimentalSerializationApi::class)
private val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.build()
您遇到的问题与Retrofit中的JSON反序列化过程有关。当服务器返回 null 时,JSON 响应不是一个有效的 JSON 数组,而是一个 JSON 空值。尝试将响应反序列化为帖子列表时,这会导致 UnexpectedValueError。
要解决此问题,您可以为您的 Post 类创建一个自定义 JSON 反序列化器,以正确处理空值。这是一个例子:
object PostJsonDeserializer : JsonDeserializer<List<Post>?> {
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): List<Post>? {
if (json == null || json.isJsonNull) {
return null
}
return context?.deserialize<List<Post>>(json, typeOfT)
}
}
这个反序列化器检查 JSON 元素是否为 null,如果是则返回 null。如果该元素不为 null,它将反序列化委托给 JsonDeserializationContext 提供的默认反序列化器。
要在 Retrofit 中使用这个反序列化器,您需要在您的 JSON 转换器工厂注册它:
private val json = Json5 {
prettyPrint = true
serializersModule = SerializersModule {
contextual(Post::class, PostJsonSerializer)
}
deserializersModule = DeserializersModule {
contextual(List::class, PostJsonDeserializer)
}
}
private val retrofit = Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) .build()
在这里,我们将 PostJsonDeserializer 注册到我们的 JSON 配置的 DeserializersModule 中。这将确保 Retrofit 在响应中遇到空 JSON 值时使用我们的自定义反序列化器。
使用此设置,您的 getPosts 方法现在应该在服务器发送空响应时返回 null,并在响应为非空时返回帖子列表。