【问题标题】:JSON Response Using Retrofit on Android在 Android 上使用 Retrofit 的 JSON 响应
【发布时间】:2016-10-01 16:34:01
【问题描述】:

我能够使用 OkHttp3 获取 JSON 响应,并且我想使用 Retrofit 解析响应以从中获取名称和图像。我查看了 Retrofit 网站和一些教程,但过程仍然不清楚。

这是我获取 JSON 响应的 OkHttp3 代码:

 Request request = new Request.Builder().url(url).build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

            Headers responseHeaders = response.headers();
            for (int i = 0, size = responseHeaders.size(); i < size; i++) {
                System.out.println(responseHeaders.name(i) + responseHeaders.value(i));
            }
            System.out.println(response.body().string());
            String jData = response.body().string();// I want to parse jData using Retrofit

        }
    });

JSON 响应如下所示:

我想获取每个艺术家的姓名、ID 和图像,非常感谢任何帮助。

更新

我添加了 Pojo 类,其中之一是 Item 类:

public class Item {

@SerializedName("external_urls")
@Expose
private ExternalUrls externalUrls;
@SerializedName("followers")
@Expose
private Followers followers;
@SerializedName("genres")
@Expose
private List<Object> genres = new ArrayList<Object>();
@SerializedName("href")
@Expose
private String href;
@SerializedName("id")
@Expose
private String id;
@SerializedName("images")
@Expose
private List<Object> images = new ArrayList<Object>();
@SerializedName("name")
@Expose
private String name;
@SerializedName("popularity")
@Expose
private Integer popularity;
@SerializedName("type")
@Expose
private String type;
@SerializedName("uri")
@Expose
private String uri;

/**
 *
 * @return
 * The externalUrls
 */
public ExternalUrls getExternalUrls() {
    return externalUrls;
}

/**
 *
 * @param externalUrls
 * The external_urls
 */
public void setExternalUrls(ExternalUrls externalUrls) {
    this.externalUrls = externalUrls;
}

/**
 *
 * @return
 * The followers
 */
public Followers getFollowers() {
    return followers;
}

/**
 *
 * @param followers
 * The followers
 */
public void setFollowers(Followers followers) {
    this.followers = followers;
}

/**
 *
 * @return
 * The genres
 */
public List<Object> getGenres() {
    return genres;
}

/**
 *
 * @param genres
 * The genres
 */
public void setGenres(List<Object> genres) {
    this.genres = genres;
}

/**
 *
 * @return
 * The href
 */
public String getHref() {
    return href;
}

/**
 *
 * @param href
 * The href
 */
public void setHref(String href) {
    this.href = href;
}

/**
 *
 * @return
 * The id
 */
public String getId() {
    return id;
}

/**
 *
 * @param id
 * The id
 */
public void setId(String id) {
    this.id = id;
}

/**
 *
 * @return
 * The images
 */
public List<Object> getImages() {
    return images;
}

/**
 *
 * @param images
 * The images
 */
public void setImages(List<Object> images) {
    this.images = images;
}

/**
 *
 * @return
 * The name
 */
public String getName() {
    return name;
}

/**
 *
 * @param name
 * The name
 */
public void setName(String name) {
    this.name = name;
}

/**
 *
 * @return
 * The popularity
 */
public Integer getPopularity() {
    return popularity;
}

/**
 *
 * @param popularity
 * The popularity
 */
public void setPopularity(Integer popularity) {
    this.popularity = popularity;
}

/**
 *
 * @return
 * The type
 */
public String getType() {
    return type;
}

/**
 *
 * @param type
 * The type
 */
public void setType(String type) {
    this.type = type;
}

/**
 *
 * @return
 * The uri
 */
public String getUri() {
    return uri;
}

/**
 *
 * @param uri
 * The uri
 */
public void setUri(String uri) {
    this.uri = uri;
}

}

以下是我在活动中使用 Retrofit 的方式:

    private void loadJSON() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.spotify.com")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    final Artists_Interface request = retrofit.create(Artists_Interface.class);

    Call<Item> call = request.getArtists();
    call.enqueue(new Callback<Item>() {
        @Override
        public void onResponse(Call<Item> call, Response<Item> response) {
            if(response.isSuccessful()){
                Item artist = response.body();
                System.out.println("THE NAME::::. : " + artist.getName());
            }
            else{
                System.out.println(" :::. NOO RESPONSE .::: " );
            } 
        }

        @Override
        public void onFailure(Call<Item> call, Throwable t) {
            System.out.println("onFAIL::: " + t);
        }
    });

这里是改造界面的样子:

public interface Artists_Interface {

@GET("/v1/search?q=Beyonce&type=artist")
Call<Item> getArtists();

}

我得到 artist.getName() 等于 null。我需要进入 JSON 正文中“项目”内的名称、ID 和图像,并将它们传递给 listView 或 recyclerView 适配器

【问题讨论】:

  • Response 类是否属于改造包?
  • 这是一个 OkHttp3 响应
  • 那么问题出在哪里?你有 JSON,只需手动解析或使用 GSON 解析即可。
  • 我需要使用 Retrofit 来提取数据

标签: android json retrofit okhttp3


【解决方案1】:

这是错误的,

Headers responseHeaders = response.headers();
            for (int i = 0, size = responseHeaders.size(); i < size; i++) {
                System.out.println(responseHeaders.name(i) + responseHeaders.value(i));
            }

您试图在标头中查找名称、ID 等数据,而信息在响应的正文中。

只需为您的数据模型创建一个 POJO,然后将信息从响应对象检索到模型中。然后你可以简单地使用 getter 和 setter 来访问你需要的数据。

更新

您可以使用此站点http://www.jsonschema2pojo.org 轻松创建您的 POJO。只需复制并粘贴您的 JSON,它就会立即为您生成 POJO。

现在,一旦你有了 POJO,你可以手动解析它,或者使用 GSON 或 Jackson 库来轻松完成。

更新 2

这里的错误是不言自明的,

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1

它明确指出解析器需要一个数组,但在实际 JSON 中找到了一个对象。

查看实际的 JSON,它以对象而不是数组开头,那你为什么在这里使用 List,

Call<List<Item>> getArtists();

如果您查看您的 JSON,您会发现它以一个对象开头,在其中您有另一个带有关键“艺术家”的对象,然后您有一个带有关键“项目”的项目列表。

您也不需要手动执行任何操作。 www.jsonschema2pojo.org 会为您生成所有内容,您只需包含它们即可。

我不明白你为什么包含一个列表而不是一个对象。

更新 3

吸气剂,简单的吸气剂。

假设你有这个,假设。

class Data {

    Artists artists;

    Artists getArtists() {
        return artists;
    }

    class Artists {
        List<Item> list;

        List<Item> getItemList(){
            return  list;
        }
    }

    class Item {
        // You have your item class here
    }
}

现在这样做,

Call<Data> getArtists();

并获取物品,

data.getArtists().getItemList();

现在清楚了吗?

【讨论】:

  • 令我困惑的是,模型类将包含什么,一个项目数组,或者只是名称、id、图像对象?如果您能显示一个 sn-p,我将不胜感激
  • 如果这解决了您的问题,请考虑接受答案或让我知道您是否需要更多帮助。
  • 谢谢。它为响应中的所有内容生成了许多类。我应该将所有这些都包含在项目中还是只包含我需要的那些。
  • 只包括你需要的分类。
  • 我根据您的建议更新了我的问题,如果您能看一下,我将不胜感激。
【解决方案2】:

感谢大家的回答,谢谢大家。我设法通过拼凑来解决这个问题,因为 Retrofit 的文档很差,而且有些答案不够详细,无法被接受。我想从这个链接的 JSON 响应中提取数据:https://api.spotify.com/v1/search?q=Beyonce&type=artist

第一步: 创建一个 Pojo 类来反序列化响应中的项目。反序列化基本上意味着在这个 JSON 响应中,我们有“艺术家”数组,里面有“href”字符串和“项目”列表,所以正如 Aritra 建议的那样,我们可以使用 http://www.jsonschema2pojo.org 来生成将反序列化这些项目的 pojo 类我们。这是我经过一些修改后的样子:

public class Data implements Serializable{

@SerializedName("artists")
Artists artists;

public Artists getArtists() {
    return artists;
}


public static class Artists {

    @SerializedName("href")
    private String href;

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


    public String getHref(){
        return href;
    }

    public List<Item> getItems(){
        return items;
    }

}// Artists



public static class Item {
    // You have your item class here
    @SerializedName("external_urls")
    @Expose
    private ExternalUrls externalUrls;
    @SerializedName("followers")
    @Expose
    private Followers followers;
    @SerializedName("genres")
    @Expose
    private List<Object> genres = new ArrayList<Object>();
    @SerializedName("href")
    @Expose
    private String href;
    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("images")
    @Expose
    private List<Object> images = new ArrayList<Object>();
    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("popularity")
    @Expose
    private Integer popularity;
    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("uri")
    @Expose
    private String uri;


    public Item() {
        name = "";
        id = "";
        images = new ArrayList<>();
    }


    /**
     * @return The externalUrls
     */
    public ExternalUrls getExternalUrls() {
        return externalUrls;
    }

    /**
     * @param externalUrls The external_urls
     */
    public void setExternalUrls(ExternalUrls externalUrls) {
        this.externalUrls = externalUrls;
    }

    /**
     * @return The followers
     */
    public Followers getFollowers() {
        return followers;
    }

    /**
     * @param followers The followers
     */
    public void setFollowers(Followers followers) {
        this.followers = followers;
    }

    /**
     * @return The genres
     */
    public List<Object> getGenres() {
        return genres;
    }

    /**
     * @param genres The genres
     */
    public void setGenres(List<Object> genres) {
        this.genres = genres;
    }

    /**
     * @return The href
     */
    public String getHref() {
        return href;
    }

    /**
     * @param href The href
     */
    public void setHref(String href) {
        this.href = href;
    }

    /**
     * @return The id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id The id
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return The images
     */
    public List<Object> getImages() {
        return images;
    }

    /**
     * @param images The images
     */
    public void setImages(List<Object> images) {
        this.images = images;
    }

    /**
     * @return The name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return The popularity
     */
    public Integer getPopularity() {
        return popularity;
    }

    /**
     * @param popularity The popularity
     */
    public void setPopularity(Integer popularity) {
        this.popularity = popularity;
    }

    /**
     * @return The type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type The type
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * @return The uri
     */
    public String getUri() {
        return uri;
    }

    /**
     * @param uri The uri
     */
    public void setUri(String uri) {
        this.uri = uri;
    }

}// Item

}

因此,表示为 Artists 类的数组“艺术家”包含 href 字符串和项目列表元素,所有这些元素都被序列化以匹配 JSON 响应。项目列表是 Item 类的类型,其中包含许多序列化的元素,如 id、name、images.. 等。所有这些都被序列化以匹配 JSON 响应。

第二步: url 分为两部分,base 和 endpoint。我们在创建 Retrofit2 请求时使用基础。我从 onCreate 方法调用这个请求:

private void loadJSON() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.spotify.com")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    final Artists_Interface request = retrofit.create(Artists_Interface.class);

    Call<Data> call = request.getArtists();
    call.enqueue(new Callback<Data>() {
        @Override
        public void onResponse(Call<Data> call, Response<Data> response) {

            if (response.isSuccessful()) {

                System.out.println(" Href ::::. : " + response.body().getArtists().getHref());

                List<Data.Item> items = response.body().getArtists().getItems();
                    for (int i = 0; i < items.size(); i++) {
                        adapter.addArtist(items.get(i));
                    }
            }
            else { System.out.println(" :::. NO RESPONSE .::: "); }

        }// End onResponse

        @Override
        public void onFailure(Call<Data> call, Throwable t) {
            System.out.println("onFAIL::: " + t);
        }
    });

然后,我们在 Retrofit2 接口类中使用端点:

public interface Artists_Interface {

@GET("/v1/search?q=Beyonce&type=artist")
Call<Data> getArtists();

}

第三步: 只需将我们从响应中获得的值分配给我们视图中的元素。在第二步中,我将项目列表分配给了我的 recyclerView 适配器,所以我的适配器如下所示:

public class Artists_Adapter extends RecyclerView.Adapter<Artists_Adapter.ViewHolder> {

private ArrayList<Data.Item> artists;

public Artists_Adapter(ArrayList<Data.Item> artists) {
    this.artists = artists;
}

@Override
public Artists_Adapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_artists, viewGroup, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(Artists_Adapter.ViewHolder viewHolder, int i) {

    viewHolder.name.setText(artists.get(i).getName());

}

@Override
public int getItemCount() {
    if(artists == null){
        return 0;
    }
    else {
        return artists.size();
    }
}

public void addArtist(Data.Item item){

    artists.add(item);

}

public class ViewHolder extends RecyclerView.ViewHolder{
    private TextView name ;
    private ImageView imageView;
    public ViewHolder(View view) {
        super(view);

        name = (TextView)view.findViewById(R.id.name);
        imageView = (ImageView) view.findViewById(R.id.image);

    }
}

}

我的 onCreate() 方法如下所示:

    private RecyclerView recyclerView;
private ArrayList<Data.Item> data = new ArrayList<>();
private Artists_Adapter adapter;
static Context ctx;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);

    ctx = this;
    url = "https://api.spotify.com/v1/search?q=Beyonce&type=artist";

    loadJSON();
    initViews();


}// onCreate


private void initViews() {
    recyclerView = (RecyclerView) findViewById(R.id.card_recycler_view);
    recyclerView.setHasFixedSize(true);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(layoutManager);
    adapter = new Artists_Adapter(data);
    recyclerView.setAdapter(adapter);

}

【讨论】:

    【解决方案3】:

    您可以使用 android JSONObject 类,例如:

    JSONObject json = new JSONObject(response.body().string());

    创建对象后,您可以使用 .get() method 像普通 JSON 一样提取所需字段。

    【讨论】:

    • 感谢您的建议,但我需要使用Retrofit来提取数据
    • use Retrofit to extract the data 到底是什么意思?改造只会给你响应数据,对吧?您需要使用其他一些类,即 JSONObject 或使用 Gson 转换为 POJO 来访问数据。
    • 我对如何将 okhttp3 与 Retrofit 一起使用有点困惑,我更新了我的问题,看看你能不能给我一些建议,谢谢
    【解决方案4】:

    here有简单的演示,请过目

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多