简体   繁体   中英

Using dynamic keys with GSON / Retrofit 2?

I have an API which returns the following schema for all requests to collections of models:

{
    item_count: 83,
    items_per_page: 25,
    offset: 25,
    <Model>s: [
        { ... },
        { ... },
        { ... },
        ...
    ]
}

For instance, if I make a request to /api/v1/customers then this JSON will contain a customers key. If I make a request to /api/v1/products then this JSON will contain a products key.

I with to create a generic PaginatedResponse<T> class to handle the item_count , items_per_page , and offset variables like so:

public class PaginatedResponse<T> {
    private int item_count;
    private int items_per_page;
    private int offset;
    private List<T> data;

    public PaginatedResponse<T>(int item_count, int items_per_page, int offset, List<T> data) {
        this.item_count = item_count;
        this.items_per_page = items_per_page;
        this.offset = offset;
        this.data = data;
    }

    public List<T> getData() {
        return this.data;
    }
}

Is there a way to parse this JSON into my PaginatedResponse POJO?

As you have different keys for model list, <Model>s: , IMHO, you better use different models for each response. You have to remove private List<T> data; from the base response model and move it to the child model.

I've modified your code and created some sample models for your products and customers . Below given detailed example,

BasePaginatedResponse.java

public class BasePaginatedResponse {

    private int item_count;
    private int items_per_page;
    private int offset;

    public BasePaginatedResponse(
            int item_count, int items_per_page, int offset) {
        this.item_count = item_count;
        this.items_per_page = items_per_page;
        this.offset = offset;
    }

}

CustomersResponse.java

public class CustomersResponse extends BasePaginatedResponse {

    private final List<Customer> customers;

    public CustomersResponse(int item_count, int items_per_page, int offset, List<Customer> customers) {
        super(item_count, items_per_page, offset);
        this.customers = customers;
    }

    public List<Customer> getCustomers() {
        return customers;
    }

    public class Customer {
        private final String id, name;

        public Customer(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return name;
        }
    }
}

ProductsResponse.java

public class ProductsResponse extends BasePaginatedResponse {

    private final List<Customer> products;

    public ProductsResponse(int item_count, int items_per_page, int offset, List<Customer> products) {
        super(item_count, items_per_page, offset);
        this.products = products;
    }

    public List<Customer> getProducts() {
        return products;
    }

    public class Customer {
        private final String id, name;

        public Customer(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return name;
        }
    }
}

Here, I've created 3 classes. 1 base response class (parent), and 2 child classes. Parent class contains fields that are common to both child classes.

As you're using Retrofit , your ApiInterface should be something like this

interface ApiInterface{
    @GET("api/v1/customers")
    Call<CustomersResponse> getCustomers();

    @GET("api/v1/products")
    Call<ProductsResponse> getProducts();
}

If you need more clarification, ask me in the comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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