预期 BEGIN_OBJECT 但在路径 $ 处是 BEGIN_ARRAY - 使用 RxJava 处理 JSONArray 响应的 Retrofit2

Posted

技术标签:

【中文标题】预期 BEGIN_OBJECT 但在路径 $ 处是 BEGIN_ARRAY - 使用 RxJava 处理 JSONArray 响应的 Retrofit2【英文标题】:Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $ - Retrofit2 with RxJava handling JSONArray response 【发布时间】:2021-06-30 18:18:40 【问题描述】:

我能够使其与 JSON 对象响应一起工作,但是当我尝试 JSON 数组响应时出现错误

Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $

假设我正在使用这个 JSON 数组

[
  
    "id": 272846,
    "date": "2021-04-04T15:26:48",
    "link": "https://sample.com/crypto-that-surged-by-1250-in-2021-teams-up-with-cardano/",
    "title": 
      "rendered": "sample"
    ,
    "content": 
      "rendered": "sample",
      "protected": false
    ,
    "author": 52,
    "jetpack_featured_media_url": "https://sample.com/wp-content/uploads/2021/01/Untitled-design-3-1.jpg"
  ,
  
    "id": 272841,
    "date": "2021-04-04T11:03:54",
    "link": "https://sample.com/global-financial-services-company-btig-is-bullish-on-bitcoin-and-microstrategy/",
    "title": 
      "rendered": "sample"
    ,
    "content": 
      "rendered": "sample",
      "protected": false
    ,
    "author": 52,
    "jetpack_featured_media_url": "https://sample.com/wp-content/uploads/2021/04/3-feb-2021-05-1024x576-1.jpg"
  
]

使用这个plugin生成的Kotlin(Codegen)类

class NewsItemModels : ArrayList<NewsItemModel>()
@JsonClass(generateAdapter = true)
data class NewsItemModel(
    @Json(name = "author")
    val author: Int,
    @Json(name = "content")
    val content: Content,
    @Json(name = "date")
    val date: String,
    @Json(name = "id")
    val id: Int,
    @Json(name = "jetpack_featured_media_url")
    val jetpackFeaturedMediaUrl: String,
    @Json(name = "link")
    val link: String,
    @Json(name = "title")
    val title: Title
)

有了这样的服务

 @GET("posts")
    fun getNewsItems(
        @Query("_fields") key: String,
        @Query("per_page") part: String,
        @Query("categories") category: String
    ):
            Observable<NewsItemModels>

服务接口

companion object 

        fun create(baseUrl: String): EndpointServices 

            val retrofit = Retrofit.Builder()
                .addCallAdapterFactory(
                    RxJava2CallAdapterFactory.create()
                )
                .addConverterFactory(
                    MoshiConverterFactory.create()
                )
                .baseUrl(baseUrl)
                .build()

            return retrofit.create(EndpointServices::class.java)

        

    

正在抓取

fetch.getNewsItems(
            "author,id,title,content,date,link,jetpack_featured_media_url",
            "30",
            categoryId
        ) //Get the first channel id
            .subscribeOn(Schedulers.io())
            .observeOn(androidSchedulers.mainThread())
            .subscribe(
                 result ->
                    Log.wtf("WTF", "$result")
                    swipeRefreshLayout.isRefreshing = false
                ,
                 error ->
                    Log.wtf("WTF", "$error.message")
                    swipeRefreshLayout.isRefreshing = false
                
            )

我能够使用 JSON 对象响应,但不能尽可能多地使用 JSONArray 我只需要一个 Retrofit.Builder 代码。这里缺少什么?

【问题讨论】:

【参考方案1】:

你可以这样做:

    @GET("posts")
    fun getNewsItems(
        @Query("_fields") key: String,
        @Query("per_page") part: String,
        @Query("categories") category: String
    ): Observable<List<NewsItemModel>>

或将NewsItemModels 的定义更新为:

typealias NewsItemModels = List<NewsItemModel>

错误信息:

预期为 BEGIN_OBJECT,但在路径 $ 处为 BEGIN_ARRAY

来自 Gson,它告诉您,根据您定义 getNewsItems 的方式,它需要一个对象(您将 NewsItemModels 定义为一个类),但它正在获取一个数组。

在您的示例 JSON 中,接收到的有效负载是一个数组,因此您需要将返回类型更新为内联 List 或使用 typealias

【讨论】:

我试过 Observable&lt;List&lt;NewsItemModel&gt;&gt; 我只是得到另一个错误将尝试 typealias,我使用的是 Moshi 而不是 GSON。 对不起,我猜 Moshi 和 Gson 也有类似的错误信息。我提出的两种解决方案都是等效的。您确定在更新签名时收到相同的错误消息吗? List&lt;NewsItemModel&gt; 出现什么错误? 这很奇怪,我之前尝试过很多次但都失败了,或者我可能通过了不同的类型。无论如何,它现在只适用于Observable&lt;List&lt;NewsItemModel&gt;&gt;,所以我现在删除类NewsItemModels。但是,当我尝试Observable&lt;ArrayList&lt;NewsItemModel&gt;&gt; 时,它给出了一个错误java.lang.IllegalArgumentException: Unable to create converter for java.util.ArrayList&lt;com.app.app.NewsItemModel&gt; 这是为什么? 也许 ArrayList 不是内置适配器之一:github.com/square/moshi#built-in-type-adapters 和 List 肯定在那里

以上是关于预期 BEGIN_OBJECT 但在路径 $ 处是 BEGIN_ARRAY - 使用 RxJava 处理 JSONArray 响应的 Retrofit2的主要内容,如果未能解决你的问题,请参考以下文章

预期 BEGIN_OBJECT 但在第 1 行第 1 列路径为 STRING - Laravel 到改造 2

获得错误预期BEGIN_ARRAY但在第1行第2列路径$是BEGIN_OBJECT

改造后请求错误 - java.lang.IllegalStateException: 预期 BEGIN_OBJECT 但在第 1 行第 1 列路径 $

AsyncTask 预期为 BEGIN_OBJECT,但在第 1 行第 2 列路径 $ 处为 BEGIN_ARRAY

Retrofit2 Android:预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 处为 BEGIN_OBJECT

更改我的程序接受文件的方式将从GSON创建此错误:预期BEGIN_ARRAY但在第1行第2列路径$ BEGIN_OBJECT?