简体   繁体   English

在Android上使用翻新的JSON响应

[英]JSON Response Using Retrofit on Android

I'm able to get JSON response using OkHttp3, and I want to use Retrofit to parse the response to get the name and the image from it. 我可以使用OkHttp3获得JSON响应,并且我想使用Retrofit来解析响应以从中获取名称和图像。 I looked into Retrofit website and some tutorials, but still the process not clear. 我查看了Retrofit网站和一些教程,但过程仍然不清楚。

Here is my OkHttp3 code to get JSON response: 这是我的OkHttp3代码以获取JSON响应:

 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

        }
    });

The JSON response looks like this: JSON响应如下所示:

在此处输入图片说明

I want to get the name, id, and the image of each artist, any help is greatly appreciated. 我想获取每个艺术家的姓名,身份证和图像,对我们的帮助非常感谢。

UPDATE 更新

I added Pojo classes one of them is Item class: 我添加了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;
}

} }

Here how I'm using Retrofit in my activity: 这是我在活动中如何使用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);
        }
    });

And here how the retrofit interface look like: 改造界面如下所示:

public interface Artists_Interface {

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

} }

I get artist.getName() equals null. 我得到artist.getName()等于null。 I need to get into name, id, and images that are inside "items" in JSON body and pass them to listView or recyclerView adapter 我需要输入JSON正文中“项目”内的名称,id和图像,并将它们传递给listView或recyclerView适配器

This is wrong, 错了

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

You are trying to find the name, id, etc. data in the headers, while the information is in the body of the response. 您试图在标题中查找名称,ID等数据,而该信息仍在响应的正文中。

Just create a POJO for your data model and retrieve the information into the model from the response object. 只需为您的数据模型创建一个POJO,然后从响应对象中将信息检索到模型中即可。 Then you can just simply use getters and setters to access your required data. 然后,您只需使用getter和setter即可访问所需的数据。

UPDATE 更新

You can create your POJO easily using this site, http://www.jsonschema2pojo.org . 您可以使用此网站http://www.jsonschema2pojo.org轻松创建POJO。 Just copy and paste your JSON and it will generate the POJOs for you instantly. 只需复制并粘贴您的JSON,它将立即为您生成POJO。

Now once you have the POJO, you can either manually parse it or use GSON or Jackson library to do it easily. 现在,有了POJO之后,您可以手动解析它,或者使用GSON或Jackson库轻松进行。

UPDATE 2 更新2

The error is quite self-explanatory here, 这里的错误是很不言自明的,

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1

It clearly states that the parser expected an array but found an object in the actual JSON. 它明确指出,解析器需要一个数组,但在实际的JSON中找到了一个对象。

See the actual JSON, it starts with an object and not an array , so why are you using List here, 请参阅实际的JSON,它以一个对象而不是一个数组开头 ,那么为什么在这里使用List,

Call<List<Item>> getArtists();

If you look at your JSON you can see that it starts with an object, inside which you have another object with key "artists" and then you have a list of items with key "items". 如果查看您的JSON,您会发现它以一个对象开头,在该对象内部您有另一个带有键“艺术家”的对象,然后有一个带有键“项目”的项目列表。

You also didn't need to do anything manually. 您也不需要手动执行任何操作。 www.jsonschema2pojo.org would have generated everything for you, you just had to include them. www.jsonschema2pojo.org将为您生成所有内容,而您只需要包含它们即可。

I don't understand why you have included a List instead of an object. 我不明白为什么您要包含列表而不是对象。

UPDATE 3 更新3

Getters man, simple getters. 吸气剂的人,简单的吸气剂。

Suppose you have this, suppose . 假设您有这个, 假设

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
    }
}

Now do this, 现在做

Call<Data> getArtists();

and to get items, 并获得物品,

data.getArtists().getItemList();

Is that now clear? 现在清楚了吗?

I appreciate all answers, thanks to everyone. 我感谢所有答案,感谢大家。 I managed to solve the problem by putting pieces together since Retrofit has poor documentation, and some answers aren't detailed enough to be accepted. 由于Retrofit的文档不多,并且一些答案不够详细,无法接受,因此我设法通过拼凑起来解决了问题。 I wanted to extract data from JSON response from this link: https://api.spotify.com/v1/search?q=Beyonce&type=artist 我想从此链接的JSON响应中提取数据: https : //api.spotify.com/v1/search?q=Beyonce&type=artist

Step1: Create a Pojo class to deserialize the items in the response. 步骤1:创建Pojo类以反序列化响应中的项目。 deserializing basically means that in this JSON response, we have "artists" array and inside it "href" string and "items" list, so as Aritra suggested, we can use http://www.jsonschema2pojo.org to generate the pojo classes that will deserialize these items for us. 反序列化基本上意味着在此JSON响应中,我们具有“ artists”数组,并且在其中具有“ href”字符串和“ items”列表,因此正如Aritra建议的那样,我们可以使用http://www.jsonschema2pojo.org生成pojo类这将为我们反序列化这些项目。 Here how mine look like after some modification: 经过一些修改后,我的样子如下:

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

} }

So, the array "artists" represented as Artists class that contains href String and items list elements all serialized to match the JSON response. 因此,表示为Artists类的数组“ artists”包含href字符串和项目列表元素,这些元素均已序列化以匹配JSON响应。 The items list is of type Item class, which contains many serialized elements, like id, name, images.. etc. all serialized to mach the JSON response. 项目列表的类型为Item类,其中包含许多序列化的元素,例如id,名称,图像等。所有这些元素都已序列化以实现JSON响应。

Step2: The url is divided into 2 parts, a base and an endpoint. 步骤2:网址分为两部分,基础部分和终结点。 We use the base when we create Retrofit2 request. 创建Retrofit2请求时,我们使用基础。 I'm calling this request from onCreate method: 我从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);
        }
    });

Then, we use the endpoint in the Retrofit2 interface class: 然后,我们在Retrofit2接口类中使用端点:

public interface Artists_Interface {

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

} }

Step3: Just assign the values we got from the response to the elements in our views. 步骤3:只需将我们从响应中获得的值分配给视图中的元素。 In step two I assigned the items list to the my recyclerView adapter, so here how my adapter look like: 在第二步中,我将项目列表分配给了我的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);

    }
}

} }

And here how my onCreate() method look like: 我的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);

}

You can use the android JSONObject class like: 您可以使用android JSONObject类,例如:

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

After creating the object you can use the .get() method to extract the required fields like a normal JSON. 创建对象后,您可以使用.get() 方法提取所需字段,例如普通的JSON。

有简单的演示在这里 ,请通过它去

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM