【问题标题】:How to parse JSON array while using Spotify APIs?使用 Spotify API 时如何解析 JSON 数组?
【发布时间】:2020-07-19 10:45:12
【问题描述】:

在使用 Spotify 搜索 API 时,我想收到专辑列表。但是,总是有一个错误,它期望一个数组但得到一个对象。但是在我的代码中,我只将类型设置为数组。所以我不知道我哪里出错了。

这是 Spotify 文档-https://developer.spotify.com/documentation/web-api/reference/search/search/

主要活动(我从登录活动中获得静态令牌)

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSearchEditText = findViewById(R.id.search_edittext);
        mSearchButton = findViewById(R.id.search_button);
        mTestTextView = findViewById(R.id.test_textview);
        mAlbumList = new ArrayList<>();
        mAlbum = new Album();

        retrofitOperations();

        mSearchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (mSearchEditText.getText() != null) {
                    searchForArt(mSearchEditText.getText().toString());
                }
            }
        });

    }

    private void searchForArt(String text) {

        text = text.replace(" ", "&20");
        HashMap<String, String> parameters = new HashMap<>();
        parameters.put("Authorization", "Bearer " + TOKEN);

        Call<Album> call = mSpotifyService.getAlbum(text, "album", parameters);
        Log.d(TAG, "searchForArt: started call");
        call.enqueue(new Callback<Album>() {
            @Override
            public void onResponse(@NonNull Call<Album> call, @NonNull Response<Album> response) {

                if (!response.isSuccessful()) {

                    Toast.makeText(MainActivity.this, "Response not successful", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "onResponse: not successful");
                    return;

                }

                Log.d(TAG, "onResponse: successful");
                mTestTextView.setText(null);
                mAlbum = response.body();
                //for (Album album : mAlbumList) {

                List<Item> itemList = mAlbum.getItemList();

                for (Item item : itemList) {

                    List<Image> imageList = item.getImageList();

                    for (Image image : imageList) {

                        mTestTextView.append(image.getUrl() + "\n");

                    }

                }
                // }

            }

            @Override
            public void onFailure(Call<Album> call, Throwable t) {

                Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                Log.d(TAG, "onFailure: call failure " + t.getMessage());

            }
        });

    }

    private void retrofitOperations() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.spotify.com/v1/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        mSpotifyService = retrofit.create(SpotifyService.class);

    }

SpotifyService 接口

public interface SpotifyService {

    @GET("search")
    Call<Album> getAlbum(@Query("q") String q,
                         @Query("type") String type,
                         @HeaderMap Map<String,String> headers);

}

专辑类

public class Album implements Parcelable {

    @SerializedName("items")
    private List<Item> itemList;

    public Album() {
    }

    public List<Item> getItemList() {
        return itemList;
    }

    protected Album(Parcel in) {
        itemList = in.createTypedArrayList(Item.CREATOR);
    }

    public static final Creator<Album> CREATOR = new Creator<Album>() {
        @Override
        public Album createFromParcel(Parcel in) {
            return new Album(in);
        }

        @Override
        public Album[] newArray(int size) {
            return new Album[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeTypedList(itemList);
    }
}

物品类别

public class Item implements Parcelable {

    @SerializedName("images")
    private List<Image> imageList;

    public Item() {
    }

    public List<Image> getImageList() {
        return imageList;
    }

    public void setImageList(List<Image> imageList) {
        this.imageList = imageList;
    }

    protected Item(Parcel in) {
    }

    public static final Creator<Item> CREATOR = new Creator<Item>() {
        @Override
        public Item createFromParcel(Parcel in) {
            return new Item(in);
        }

        @Override
        public Item[] newArray(int size) {
            return new Item[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    }
}

图像类

public class Image implements Parcelable{

    @SerializedName("url")
    private String url;

    public Image() {
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    protected Image(Parcel in) {
        url = in.readString();
    }

    public static final Creator<Image> CREATOR = new Creator<Image>() {
        @Override
        public Image createFromParcel(Parcel in) {
            return new Image(in);
        }

        @Override
        public Image[] newArray(int size) {
            return new Image[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(url);
    }
}

错误

2020-04-07 17:57:55.945 21128-21128/com.example.spotify_album_art E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.spotify_album_art, PID: 21128
    java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference
        at com.example.spotifyalbumart.MainActivity$2.onResponse(MainActivity.java:96)
        at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

【问题讨论】:

    标签: android api retrofit retrofit2 spotify


    【解决方案1】:

    您在 API 调用中收到的响应存在问题。在仅返回 Album 类的对象而不是 List&lt;Album&gt; 的 API 中。

    所以只要像下面那样做就是对 API 的请求。

    Call<Album> call = mSpotifyService.getAlbum(text, "album", parameters);
            Log.d(TAG, "searchForArt: started call");
            call.enqueue(new Callback<Album>() {
                @Override
                public void onResponse(Call<Album> call, Response<Album> response) {
    
                }
    
                @Override
                public void onFailure(Call<Album> call, Throwable t) {
    
                    Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "onFailure: call failure "+t.getMessage());
    
                }
            });
    

    在你的界面中像

    @GET("search")
        Call<Album> getAlbum(@Query("q") String q,
                                   @Query("type") String type,
                                   @HeaderMap Map<String,String> headers);
    

    【讨论】:

    • 然而,在 Spotify 官方文档中,他们提到我们将收到一个对象数组。 developer.spotify.com/documentation/web-api/reference/search/… 当我使用你的方法时` mAlbum= response.body(); ` 它给出一个错误 ` java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on an null object reference ` 这指的是 MainActivity 中的 itemList 数组
    • 如果你有所有参数然后在 Spotify 中点击 api 并检查他的响应。
    • 也在 Spotify 中显示示例响应,其中唯一的对象不是数组。 @DhruvRauthan
    • 所以我照你说的做了。在 spotify api 上尝试时,查询是:api.spotify.com/v1/search?q=gloria&type=album&limit=2。连同授权令牌。这是回复:pastebin.com/P066Rrma。但是它仍然显示错误:java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference。
    • 您的 API 调用成功,但可能是您与 Parcelable 一起使用的模型类存在问题。问题出在 MainActivity 第 96 行。如何识别代码中的确切行? @DhruvRauthan
    猜你喜欢
    • 2015-07-06
    • 2021-12-29
    • 2015-07-11
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2012-11-08
    相关资源
    最近更新 更多