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?
Answer
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
.