Retrofit returns data but the pojo object is always empty

I'm trying to consume a service by using retrofit 2. When I call it using a web browser or log the call using an interceptor, there're some results, but my pojo classes are always empty.

The json result content is similar to:

  {
      "similarartists": {
        "artist": [
        {
          "name": "Barão Vermelho",
          "mbid": "84ac395b-482b-48cb-b381-b9bc420b2dd3",
          "match": "1",
          "url": "https://www.last.fm/music/Bar%C3%A3o+Vermelho",
          "image": [],
          "streamable": "0"
        },
        "@attr": {
          "artist": "Cazuza"
        }
     }
  }

And these are my pojo classes:

public class Similarartists {

    @SerializedName("artist")
    private List<Artist> artist = new ArrayList<>();

    @SerializedName("attr")
    private Attr attr;

}

public class Artist {

    @SerializedName("name")
    private String name;

    @SerializedName("mbid")
    private String mbid;

    @SerializedName("match")
    private String match;

    @SerializedName("url")
    private String url;

    @SerializedName("image")
    private List<Object> image = new ArrayList<>();

    @SerializedName("streamable")
    private String streamable;
}

public class Attr {
    @SerializedName("artist")
    private String artist;
}

The service connection class:

public class ApiService {
    private static final String BASE_URL = "http://ws.audioscrobbler.com/";
    public static final String API_KEY = "XXXXXXXXXX";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
            .readTimeout(30, TimeUnit.SECONDS)
            .connectTimeout(30, TimeUnit.SECONDS);

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        httpClient.addInterceptor(logging);

        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();

                // Request customization: add request headers
                Request.Builder requestBuilder = original.newBuilder()
                        .header("Accept", "application/json")
                        .header("Content-Type", "application/json")
                        .method(original.method(), original.body());

                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        });

        Retrofit retrofit = builder.client(httpClient.build()).build();

        return retrofit.create(serviceClass);
    }

}

Ans this is my "button" action:

private void openSearchDialog() {
    ArtistService artistService = ApiService.createService(ArtistService.class);
    Call<Similarartists> call = artistService.getSimilar("nirvana", ApiService.API_KEY);
    call.enqueue(new Callback<Similarartists>() {
        @Override
        public void onResponse(Call<Similarartists> call, Response<Similarartists> response) {
            if (response.isSuccessful()) {
                mAdapter.setValues(response.body().getArtist());
                Log.i(TAG, "onResponse: " + response.body().toString());
            }
        }

        @Override
        public void onFailure(Call<Similarartists> call, Throwable t) {
            Log.e(TAG, "onFailure: ", t);
        }
    });
}

The problem is response.body().getArtist() is always empty. Please help me.

And this's my log result:

-01 22:51:58.844 23843-24043/com.sample.pablo.hellomusic D/OkHttp: {"similarartists":{"artist":[{"name":"Hole","mbid":"1dcc8968-f2cd-441c-beda-6270f70f2863","match":"1","url":"https://www.last.fm/music/Hole","image":[{"#text":"https://lastfm-img2.akamaized.net/i/u/34s/6687f63408074388ae703eb3905e238f.png","size":"small"},{"#text":"https://lastfm-img2.akamaized.net/i/u/64s/6687f63408074388ae703eb3905e238f.png","size":"medium"},{"#text":"https://lastfm-img2.akamaized.net/i/u/174s/6687f63408074388ae703eb3905e238f.png","size":"large"},{"#text":"https://lastfm-img2.akamaized.net/i/u/300x300/6687f63408074388ae703eb3905e238f.png","size":"extralarge"},{"#text":"https://lastfm-img2.akamaized.net/i/u/6687f63408074388ae703eb3905e238f.png","size":"mega"},{"#text":"https://lastfm-img2.akamaized.net/i/u/arQ/6687f63408074388ae703eb3905e238f.png","size":""}],"streamable":"0"}],"@attr":{"artist":"Nirvana"}}}

Upvotes: 0

Views: 541

Answers (1)

Cody Caughlan
Cody Caughlan

Reputation: 32748

Since there is a top-level key of similarartists in the response JSON I think you need another wrapper around this object, like:

public class SimilarArtistsResponse {
  @SerializedName("similarartists")
  private Similarartists similars;
}

And its this object you would specify in your Call<SimilarArtistsResponse>

Upvotes: 1

Related Questions