All the while, I’m using retrofit and JSON to POJO tool, in order to have Android app talk with API server.
The API server is using JSON as response.
Recently, I encounter stock related response, which looks like this
{
"APPL": {
"quote": {
"symbol": "AAPL",
"lastPrice": 1.23
},
"stats": {
"dividendRate":2.52
}
},
"GOOGL": {
"quote": {
"symbol": "GOOGL",
"lastPrice": 4.56
},
"stats": {
"dividendRate":7.89
}
}
}
APPL and GOOGL, are company stock codes. I view them as value
. Hence, I don’t expect them to be placed at JSON’s name field (Left hand side)
I can hardly generate a suitable set of classes for the above response.
If I plug the JSON output directly to http://www.jsonschema2pojo.org/ , the result I’m getting are
public class BatchResponse {
@SerializedName("APPL")
@Expose
private APPL aPPL;
@SerializedName("GOOGL")
@Expose
private GOOGL gOOGL;
public APPL getAPPL() {
return aPPL;
}
public void setAPPL(APPL aPPL) {
this.aPPL = aPPL;
}
public GOOGL getGOOGL() {
return gOOGL;
}
public void setGOOGL(GOOGL gOOGL) {
this.gOOGL = gOOGL;
}
}
public class APPL {
@SerializedName("quote")
@Expose
private Quote quote;
@SerializedName("stats")
@Expose
private Stats stats;
public Quote getQuote() {
return quote;
}
public void setQuote(Quote quote) {
this.quote = quote;
}
public Stats getStats() {
return stats;
}
public void setStats(Stats stats) {
this.stats = stats;
}
}
public class GOOGL {
@SerializedName("quote")
@Expose
private Quote quote;
@SerializedName("stats")
@Expose
private Stats stats;
public Quote getQuote() {
return quote;
}
public void setQuote(Quote_ quote) {
this.quote = quote;
}
public Stats getStats() {
return stats;
}
public void setStats(Stats stats) {
this.stats = stats;
}
}
public class Quote {
@SerializedName("symbol")
@Expose
private String symbol;
@SerializedName("lastPrice")
@Expose
private double lastPrice;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getLastPrice() {
return lastPrice;
}
public void setLastPrice(double lastPrice) {
this.lastPrice = lastPrice;
}
}
public class Stats {
@SerializedName("dividendRate")
@Expose
private double dividendRate;
public double getDividendRate() {
return dividendRate;
}
public void setDividendRate(double dividendRate) {
this.dividendRate = dividendRate;
}
}
Hence, if I have Tesla, Facebook, … stocks, I have to create new classes for each stock.
I was wondering, how I suppose to handle the above response using retrofit? Is there any workaround I can do on the above API response, so that I can handle them gracefully using retrofit?
Does it make sense, if I can propose the following response format to the API designer, so that application developer can handle such response easier?
{
"batch" : [
{
"quote" : {
"symbol": "AAPL",
"lastPrice": 1.23
},
"stats" : {
"dividendRate":2.52
}
},
{
"quote" : {
"symbol": "GOOGL",
"lastPrice": 4.56
},
"stats" : {
"dividendRate":7.89
}
}
]
}
If using the above proposed API response, I can generate a better POJO classes.
public class BatchResponse {
@SerializedName("batch")
@Expose
private List<Batch> batch = null;
public List<Batch> getBatch() {
return batch;
}
public void setBatch(List<Batch> batch) {
this.batch = batch;
}
}
public class Quote {
@SerializedName("symbol")
@Expose
private String symbol;
@SerializedName("lastPrice")
@Expose
private double lastPrice;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public double getLastPrice() {
return lastPrice;
}
public void setLastPrice(double lastPrice) {
this.lastPrice = lastPrice;
}
}
public class Stats {
@SerializedName("dividendRate")
@Expose
private double dividendRate;
public double getDividendRate() {
return dividendRate;
}
public void setDividendRate(double dividendRate) {
this.dividendRate = dividendRate;
}
}
3
Answers
I manage to find a workaround.
It is using Map of String to BatchResponse
It looks like
The
BatchResponse
class ishow I suppose to handle the above response using retrofit?
– You just need to use the same class. just change the SerializedName(“APPL”) eg for Tesla SerializedName(“TESLA”) as we are getting the same response inside. so we dont need to create the whole class again and again.
Does it make sense, if I can propose the following response format to the API designer, so that application developer can handle such response easier?
More than an answer this might come across as a suggestion.
The developer must have some reason behind the way the code was developed for creating the JSON response. Questions you could ask are if some other application is also latching on to the response in this format, or if there are applications under development which require data in this format etc. If there are other applications that consume the data, then the answer by @Harminder Singh seems the right way. If this response is consumed just by the application being developed by you, I do not see any reason in having it the way you want it and you can ask the developer to change it to your specification.