I'm calling in my app Unsplash API. I want to get photos based on the keyword.
But I can't something is wrong in my Model or URL and I get this error :
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
I'm using Paging library with LiveData for this but I don't know how to do it properly.
Here is my PhotoDataSource:
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Photo>) {
networkState.postValue(NetworkState.LOADING)
initialLoad.postValue(NetworkState.LOADING)
photoService.search("nature", FIRST_PAGE_NUMBER, params.requestedLoadSize).enqueue(object : Callback<List<Photo>>{
override fun onFailure(call: Call<List<Photo>>, t: Throwable) {
// keep a Completable for future retry
setRetry(Action { loadInitial(params, callback) })
val error = NetworkState.error(t.message)
// publish the error
networkState.postValue(error)
initialLoad.postValue(error)
}
override fun onResponse(call: Call<List<Photo>>, response: Response<List<Photo>>) {
if (response.body() != null) {
setRetry(null)
val data = response.body()
val items = data?.map { it } ?: emptyList()
networkState.postValue(NetworkState.LOADED)
initialLoad.postValue(NetworkState.LOADED)
callback.onResult(items, null, FIRST_PAGE_NUMBER + INCREMENT_PAGE_VALUE)
}
}
})
}
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Photo>) {
networkState.postValue(NetworkState.LOADING)
Timber.d("Fetching next page: ${params.key}")
photoService.search("nature", params.key, params.requestedLoadSize).enqueue(object : Callback<List<Photo>> {
override fun onFailure(call: Call<List<Photo>>, t: Throwable) {
// keep a Completable for future retry
setRetry(Action { loadAfter(params, callback) })
// publish the error
networkState.postValue(NetworkState.error(t.message))
}
override fun onResponse(call: Call<List<Photo>>, response: Response<List<Photo>>) {
if (response.body() != null) {
val data = response.body()
val items = data?.map { it } ?: emptyList()
setRetry(null)
networkState.postValue(NetworkState.LOADED)
callback.onResult(items, params.key + INCREMENT_PAGE_VALUE)
}
}
})
}
Here, I have Photo Object:
@Parcelize
data class Photo (val urls: @RawValue Urls? = null,
val color: String? = null,
val width: Int? = null,
val height: Int? = null,
val created_at: String? = null,
val id: String? = null,
val user: @RawValue User? = null,
val links: @RawValue Links? = null,
val likes: Int? = null,
val downloads: Int? = null,
val description: String? = null,
val location: @RawValue Location? = null,
val exif: @RawValue Exif? = null
):Parcelable
And here I'm calling the API, PhotoService:
@GET("search/photos")
fun search(@Query("query") query: String, @Query("per_page") perPage: Int, @Query("page") page: Int): Call<List<Photo>>
Here is the full code from the JSON Response:
{
"total": 133,
"total_pages": 7,
"results": [
{
"id": "eOLpJytrbsQ",
"created_at": "2014-11-18T14:35:36-05:00",
"width": 4000,
"height": 3000,
"color": "#A7A2A1",
"likes": 286,
"liked_by_user": false,
"description": "A man drinking a coffee.",
"user": {
"id": "Ul0QVz12Goo",
"username": "ugmonk",
"name": "Jeff Sheldon",
"first_name": "Jeff",
"last_name": "Sheldon",
"instagram_username": "instantgrammer",
"twitter_username": "ugmonk",
"portfolio_url": "http://ugmonk.com/",
"profile_image": {
"small": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
"medium": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
"large": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202"
},
"links": {
"self": "https://api.unsplash.com/users/ugmonk",
"html": "http://unsplash.com/@ugmonk",
"photos": "https://api.unsplash.com/users/ugmonk/photos",
"likes": "https://api.unsplash.com/users/ugmonk/likes"
}
},
"current_user_collections": [],
"urls": {
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
},
"links": {
"self": "https://api.unsplash.com/photos/eOLpJytrbsQ",
"html": "http://unsplash.com/photos/eOLpJytrbsQ",
"download": "http://unsplash.com/photos/eOLpJytrbsQ/download"
}
},
// more photos ...
]
}
I have no idea what to do, I saw a lot of tutorials on the internet but I couldn't do anything. I hope you could help me, please.
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
This error specify that in your response one of keywords have object but you are accessing it as a array object.
Solution:-
Check that keywords which is mention as object.
Try to make as object in your response Object
@GET("search/photos")
fun search(@Query("query") query: String, @Query("per_page") perPage: Int, @Query("page") page: Int): Call<Example>
EDIT:-
Use these classes in your project and Use Example for retrofit result.
Example.class
public class Example {
@SerializedName("total")
@Expose
private Integer total;
@SerializedName("total_pages")
@Expose
private Integer totalPages;
@SerializedName("results")
@Expose
private List<Result> results = null;
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
}
Links.class
public class Links {
@SerializedName("self")
@Expose
private String self;
@SerializedName("html")
@Expose
private String html;
@SerializedName("photos")
@Expose
private String photos;
@SerializedName("likes")
@Expose
private String likes;
public String getSelf() {
return self;
}
public void setSelf(String self) {
this.self = self;
}
public String getHtml() {
return html;
}
public void setHtml(String html) {
this.html = html;
}
public String getPhotos() {
return photos;
}
public void setPhotos(String photos) {
this.photos = photos;
}
public String getLikes() {
return likes;
}
public void setLikes(String likes) {
this.likes = likes;
}
}
Links_.class
public class Links_ {
@SerializedName("self")
@Expose
private String self;
@SerializedName("html")
@Expose
private String html;
@SerializedName("download")
@Expose
private String download;
public String getSelf() {
return self;
}
public void setSelf(String self) {
this.self = self;
}
public String getHtml() {
return html;
}
public void setHtml(String html) {
this.html = html;
}
public String getDownload() {
return download;
}
public void setDownload(String download) {
this.download = download;
}
}
ProfileImage.class
public class ProfileImage {
@SerializedName("small")
@Expose
private String small;
@SerializedName("medium")
@Expose
private String medium;
@SerializedName("large")
@Expose
private String large;
public String getSmall() {
return small;
}
public void setSmall(String small) {
this.small = small;
}
public String getMedium() {
return medium;
}
public void setMedium(String medium) {
this.medium = medium;
}
public String getLarge() {
return large;
}
public void setLarge(String large) {
this.large = large;
}
}
Result.class
public class Result {
@SerializedName("id")
@Expose
private String id;
@SerializedName("created_at")
@Expose
private String createdAt;
@SerializedName("width")
@Expose
private Integer width;
@SerializedName("height")
@Expose
private Integer height;
@SerializedName("color")
@Expose
private String color;
@SerializedName("likes")
@Expose
private Integer likes;
@SerializedName("liked_by_user")
@Expose
private Boolean likedByUser;
@SerializedName("description")
@Expose
private String description;
@SerializedName("user")
@Expose
private User user;
@SerializedName("current_user_collections")
@Expose
private List<Object> currentUserCollections = null;
@SerializedName("urls")
@Expose
private Urls urls;
@SerializedName("links")
@Expose
private Links_ links;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Integer getLikes() {
return likes;
}
public void setLikes(Integer likes) {
this.likes = likes;
}
public Boolean getLikedByUser() {
return likedByUser;
}
public void setLikedByUser(Boolean likedByUser) {
this.likedByUser = likedByUser;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Object> getCurrentUserCollections() {
return currentUserCollections;
}
public void setCurrentUserCollections(List<Object> currentUserCollections) {
this.currentUserCollections = currentUserCollections;
}
public Urls getUrls() {
return urls;
}
public void setUrls(Urls urls) {
this.urls = urls;
}
public Links_ getLinks() {
return links;
}
public void setLinks(Links_ links) {
this.links = links;
}
}
Urls.class
public class Urls {
@SerializedName("raw")
@Expose
private String raw;
@SerializedName("full")
@Expose
private String full;
@SerializedName("regular")
@Expose
private String regular;
@SerializedName("small")
@Expose
private String small;
@SerializedName("thumb")
@Expose
private String thumb;
public String getRaw() {
return raw;
}
public void setRaw(String raw) {
this.raw = raw;
}
public String getFull() {
return full;
}
public void setFull(String full) {
this.full = full;
}
public String getRegular() {
return regular;
}
public void setRegular(String regular) {
this.regular = regular;
}
public String getSmall() {
return small;
}
public void setSmall(String small) {
this.small = small;
}
public String getThumb() {
return thumb;
}
public void setThumb(String thumb) {
this.thumb = thumb;
}
}
User.class
public class User {
@SerializedName("id")
@Expose
private String id;
@SerializedName("username")
@Expose
private String username;
@SerializedName("name")
@Expose
private String name;
@SerializedName("first_name")
@Expose
private String firstName;
@SerializedName("last_name")
@Expose
private String lastName;
@SerializedName("instagram_username")
@Expose
private String instagramUsername;
@SerializedName("twitter_username")
@Expose
private String twitterUsername;
@SerializedName("portfolio_url")
@Expose
private String portfolioUrl;
@SerializedName("profile_image")
@Expose
private ProfileImage profileImage;
@SerializedName("links")
@Expose
private Links links;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getInstagramUsername() {
return instagramUsername;
}
public void setInstagramUsername(String instagramUsername) {
this.instagramUsername = instagramUsername;
}
public String getTwitterUsername() {
return twitterUsername;
}
public void setTwitterUsername(String twitterUsername) {
this.twitterUsername = twitterUsername;
}
public String getPortfolioUrl() {
return portfolioUrl;
}
public void setPortfolioUrl(String portfolioUrl) {
this.portfolioUrl = portfolioUrl;
}
public ProfileImage getProfileImage() {
return profileImage;
}
public void setProfileImage(ProfileImage profileImage) {
this.profileImage = profileImage;
}
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
}
Next time try to convert your JSON into POJO from this Link.