0

I was able to make it work with a JSON object response but when I tried a JSON Array response I am having an error

Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $

Lets say I am using this JSON Array

[
  {
    "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"
  }
]

The generated Kotlin (Codegen) class using this plugin

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
)

With a service like this

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

Service interface

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)

        }

    }

Fetching

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
                }
            )

I was able to work with JSON Object response but not with JSONArray as much as possible I want only one Retrofit.Builder code. What is the missing part here?

1 Answer 1

3

You can either do:

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

or update your definition of NewsItemModels to:

typealias NewsItemModels = List<NewsItemModel>

The error message:

Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $

comes from Gson, and it's telling you that based on the way you defined the getNewsItems it's expecting an object (you defined NewsItemModels as a class) but it's getting an array.

In your example JSON the received payload it's an array so you need to update the return type to either inline the List or use a typealias.

Sign up to request clarification or add additional context in comments.

7 Comments

I tried Observable<List<NewsItemModel>> I just get another error will try typealias instead, I am using Moshi not GSON.
Sorry, I guess Moshi and Gson have a similar error message. Both solutions I proposed are equivalent. Are you sure you get the same error message when updating the signature?
what error are you getting with List<NewsItemModel>?
This is weird I tried this before many times and failed or maybe I pass a different type. Anyway it works now with just Observable<List<NewsItemModel>> so I am deleting now the class NewsItemModels. However when I tried Observable<ArrayList<NewsItemModel>> it gives an error java.lang.IllegalArgumentException: Unable to create converter for java.util.ArrayList<com.app.app.NewsItemModel> why is that?
Maybe ArrayList is not one of the built-in adapters: github.com/square/moshi#built-in-type-adapters and List is definetly there
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.