当前位置: 首页 > 知识库问答 >
问题:

如何在使用Spotify API时解析JSON数组?

满俊楠
2023-03-14

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

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

主要活动(我从loginactivity获得静态令牌)

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)

共有1个答案

雷骁
2023-03-14

在API调用中得到的响应有问题。在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);

 类似资料:
  • 问题内容: 我正在开发一个应用程序,其中我正在使用来自服务器的json格式的数据。但是我能够解析普通的json数据,但是无法解析带有数组的json数据, json响应如下 我如何读取此json数组? 注意 :我正在使用Litjson进行解析。 问题答案: 您应该按照POCO对象创建自己: LitJSON将立即反序列化此序列: 作为替代方案,您可以使用非通用变量(下面的示例会将所有数据写入控制台):

  • 问题内容: 我想解析JSON数组并使用gson。首先,我可以记录JSON输出,服务器清楚地响应客户端。 这是我的JSON输出: 我尝试了这种结构进行解析。一个类,该类取决于单个JSONArray 和所有JSONArray。 上课时间: 当我尝试使用gson时,没有错误,没有警告,也没有日志: 怎么了,我该怎么解决? 问题答案: 您可以直接解析直接类,不需要再花更多时间包装您的类,也不需要新的类:

  • 问题内容: 我想解析JSON数组并使用gson。首先,我可以记录JSON输出,服务器清楚地响应客户端。 这是我的JSON输出: 我尝试了这种结构进行解析。一个类,该类取决于单个和所有JSONArray。 上课时间: 当我尝试使用gson时,没有错误,没有警告,也没有日志: 怎么了,我该怎么解决? 问题答案: 你可以直接解析直接类,不需要再花更多时间包装你的Post类,也不需要新的类: 希望能有所帮

  • 我正在使用来解析Json数据。我的Json数据如下: GsonParse.java 我使用以下方法来解析此JSON数据。 我面对以下错误。

  • 问题内容: 我应该如何使用Node.js解析JSON?是否有一些模块可以安全地验证和解析JSON? 问题答案: 你可以简单地使用。 JSON对象的定义是ECMAScript 5规范的一部分。node.js基于Google Chrome的V8引擎构建,该引擎遵循ECMA标准。因此,node.js也有一个全局对象。JSON 注意- 可以占用当前线程,因为它是一种同步方法。因此,如果你打算解析大型JSO

  • 问题内容: 我想解析传入的JSON数据,例如: 我使用的代码是: 但是我无法分配任何东西给。有什么建议? 问题答案: 该响应是一个Map,具有单个元素,键为“ 212315952136472”。地图中没有“数据”键。如果要遍历所有条目,请使用以下命令: 如果您知道它是单元素地图,则可以直接访问: 而且,如果您知道ID(例如,如果您使用它来发出请求),则可以更简洁地访问该值: