Toni Toni - 2 years ago 150
Android Question

Parsing JSON propertly using Retrofit on Android

I want to parse a Json produced by this url:

https://blockchain.info/es/ticker

This URL generate a JSON response like so:

{
"USD" : {"15m" : 4097.85, "last" : 4097.85, "buy" : 4097.84, "sell" : 4093.37, "symbol" : "$"},
"AUD" : {"15m" : 5209.87, "last" : 5209.87, "buy" : 5209.86, "sell" : 5204.18, "symbol" : "$"},
"BRL" : {"15m" : 12985.88, "last" : 12985.88, "buy" : 12985.85, "sell" : 12971.68, "symbol" : "R$"},
"CAD" : {"15m" : 5214.82, "last" : 5214.82, "buy" : 5214.81, "sell" : 5209.12, "symbol" : "$"},
"CHF" : {"15m" : 3985.18, "last" : 3985.18, "buy" : 3985.17, "sell" : 3980.82, "symbol" : "CHF"},
"CLP" : {"15m" : 2660734.01, "last" : 2660734.01, "buy" : 2660727.51, "sell" : 2657825.14, "symbol" : "$"},
"CNY" : {"15m" : 27427.32, "last" : 27427.32, "buy" : 27427.25, "sell" : 27397.33, "symbol" : "¥"},
"DKK" : {"15m" : 25993.26, "last" : 25993.26, "buy" : 25993.2, "sell" : 25964.85, "symbol" : "kr"},
"EUR" : {"15m" : 3495.38, "last" : 3495.38, "buy" : 3495.37, "sell" : 3491.56, "symbol" : "€"},
"GBP" : {"15m" : 3180.65, "last" : 3180.65, "buy" : 3180.64, "sell" : 3177.17, "symbol" : "£"},
"HKD" : {"15m" : 32058.22, "last" : 32058.22, "buy" : 32058.14, "sell" : 32023.17, "symbol" : "$"},
"INR" : {"15m" : 262979.52, "last" : 262979.52, "buy" : 262978.88, "sell" : 262692.02, "symbol" : "₹"},
"ISK" : {"15m" : 447157.39, "last" : 447157.39, "buy" : 447156.3, "sell" : 446668.53, "symbol" : "kr"},
"JPY" : {"15m" : 454250.37, "last" : 454250.37, "buy" : 454249.26, "sell" : 453753.75, "symbol" : "¥"},
"KRW" : {"15m" : 4677285.99, "last" : 4677285.99, "buy" : 4677274.58, "sell" : 4672172.52, "symbol" : "₩"},
"NZD" : {"15m" : 5656.28, "last" : 5656.28, "buy" : 5656.26, "sell" : 5650.09, "symbol" : "$"},
"PLN" : {"15m" : 14947.54, "last" : 14947.54, "buy" : 14947.51, "sell" : 14931.2, "symbol" : "zł"},
"RUB" : {"15m" : 244110.7, "last" : 244110.7, "buy" : 244110.1, "sell" : 243843.82, "symbol" : "RUB"},
"SEK" : {"15m" : 33149.72, "last" : 33149.72, "buy" : 33149.64, "sell" : 33113.48, "symbol" : "kr"},
"SGD" : {"15m" : 5603.48, "last" : 5603.48, "buy" : 5603.46, "sell" : 5597.35, "symbol" : "$"},
"THB" : {"15m" : 136432.79, "last" : 136432.79, "buy" : 136432.46, "sell" : 136283.64, "symbol" : "฿"},
"TWD" : {"15m" : 124291.89, "last" : 124291.89, "buy" : 124291.59, "sell" : 124156.01, "symbol" : "NT$"}
}


I want to use Retrofit to get each currency as an object to be able to print all the information later on an Activity. One thing I noticed is the type of returned which I am not very sure how to define. Anyway, I am using Retrofit so just to try an example I am doing something like this:

public interface CryptoCurrencyService {

@GET("ticker")
Call<JsonObject> listCurrencies();
}


Then I have:

public class ApiClient
{

//https://blockchain.info/es/ticker


private static Retrofit retrofit = null;

static Retrofit getClient() {

retrofit = new Retrofit.Builder()
.baseUrl("https://blockchain.info/es/")
.addConverterFactory(GsonConverterFactory.create())
.build();

return retrofit;
}


}


And the class Currency:

public class Currency
{
@SerializedName("15m")
private double valueLast15m;
@SerializedName("last")
private double lastValue;
@SerializedName("buy")
private double buyValue;
@SerializedName("sell")
private double sellValue;
@SerializedName("symbol")
private String symbol;

public Currency(double valueLast15m, double lastValue, double buyValue, double sellValue, String symbol) {
this.valueLast15m = valueLast15m;
this.lastValue = lastValue;
this.buyValue = buyValue;
this.sellValue = sellValue;
this.symbol = symbol;
}

public Currency()
{
this.valueLast15m = 0.0;
this.lastValue = 0.0;
this.buyValue = 0.0;
this.sellValue = 0.0;
this.symbol = "";
}

public double getValueLast15m() {
return valueLast15m;
}

public void setValueLast15m(double valueLast15m) {
this.valueLast15m = valueLast15m;
}

public double getLastValue() {
return lastValue;
}

public void setLastValue(double lastValue) {
this.lastValue = lastValue;
}

public double getBuyValue() {
return buyValue;
}

public void setBuyValue(double buyValue) {
this.buyValue = buyValue;
}

public double getSellValue() {
return sellValue;
}

public void setSellValue(double sellValue) {
this.sellValue = sellValue;
}

public String getSymbol() {
return symbol;
}

public void setSymbol(String symbol) {
this.symbol = symbol;
}
}


So at some point at my Activity I am doing this:

CryptoCurrencyService service = ApiClient.getClient().create(CryptoCurrencyService.class);
service.listCurrencies().enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
Log.d("RESPONSE",response.body().getAsString());


}

@Override
public void onFailure(Call<JsonObject> call, Throwable t) {

Toast.makeText(getApplicationContext(),"Failure",Toast.LENGTH_LONG).show();
}
});


However I am not getting the JSON converted to String, just the response of the web ( ok : 200 ) .

I've tried :

response.body().getAsString(), response.body().toString(), response.toString().... but all I get is the http response, not the JSON, which by the way I know I got it right because if I place my mouse over the "response" object I can search the JSON object returned by doing right click under response->body->members. I've also tried to do response.body().get("members"); but it crashes.

Any idea what am I doing wrong? Can I get the list parsed directly without getting the raw json response?

Thank you very much!

Answer Source

In retrofit the parametized class of your Call should be the class corresponding to the mapping of your json response.

More a thing like this :

public interface CryptoCurrencyService {

    @GET("ticker")
    Call<Map<String, Currency>> listCurrencies();
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download