0

so I've tried to show some currency exchange on the app, but I can't even run it, I've got that error:

2019-05-01 14:34:57.260 6798-6798/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 6798
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.IllegalArgumentException: Unable to create converter for java.util.List<com.example.myapplication.Currency>
    for method CurrencyExchangeService.getCurrency
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: java.lang.IllegalArgumentException: Unable to create converter for java.util.List<com.example.myapplication.Currency>
    for method CurrencyExchangeService.getCurrency
    at retrofit2.Utils.methodError(Utils.java:52)
    at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:70)
    at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:46)
    at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:36)
    at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:168)
    at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
    at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
    at $Proxy0.getCurrency(Unknown Source)
    at com.example.myapplication.MainActivity.onCreate(MainActivity.java:33)
    at android.app.Activity.performCreate(Activity.java:7136)
    at android.app.Activity.performCreate(Activity.java:7127)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        ... 11 more
 Caused by: java.lang.IllegalArgumentException: class com.example.myapplication.Currency declares multiple JSON fields named CAD
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:64)
    at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:328)
    at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:311)
    at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:68)
        ... 22 more

Logcat navigate me to this line of code

        Call<List<Currency>> call = currencyInterface.getCurrency();

which is calling method in interface, I assume, that I've badly named the String inside @Get method.

Here's the code

MainActivity

public class MainActivity extends AppCompatActivity {
private TextView textViewResult;

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

    textViewResult = findViewById(R.id.text_view_result);

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.exchangeratesapi.io/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    CurrencyExchangeService currencyInterface = retrofit.create(CurrencyExchangeService.class);
    Call<List<Currency>> call = currencyInterface.getCurrency();
    call.enqueue(new Callback<List<Currency>>() {
        @Override
        public void onResponse(Call<List<Currency>> call, Response<List<Currency>> response) {
            List<Currency> list = response.body();

            for (Currency currency : list) {
                String content = "";
                content += "a: "+ currency.getEUR();
                content += "b: "+ currency.getCAD();
                content += "c: "+ currency.getGBP();

                textViewResult.append(content);
            }
        }

        @Override
        public void onFailure(Call<List<Currency>> call, Throwable t) {
            textViewResult.setText(t.getMessage());
        }
    });
}
}

Currency

public class Currency {

private int CAD,CHF,GBP,SEK,EUR,USD;

@SerializedName("CAD")
private String cad;


public Currency(int CAD, int CHF, int GBP, int SEK, int EUR, int USD) {
    this.CAD = CAD;
    this.CHF = CHF;
    this.GBP = GBP;
    this.SEK = SEK;
    this.EUR = EUR;
    this.USD = USD;
}

public int getCAD() {
    return CAD;
}

public int getCHF() {
    return CHF;
}

public int getGBP() {
    return GBP;
}

public int getSEK() {
    return SEK;
}

public int getEUR() {
    return EUR;
}

public int getUSD() {
    return USD;
}
}

CurrencyExchangeInterface

public interface CurrencyExchangeService {
@GET("latest?base=USD")
Call<List<Currency>> getCurrency();
}

Where's the problem? Am I right about that name in interface? So which I should use, if I want to take latest currency exchange? I am using Retrofit 2, and https://exchangeratesapi.io/ api.

  • rates is JsonArray it's not JsonObject. You're doing wrong. check response and change your model class based on that – M D May 01 '19 at 12:53
  • the problem lies here declares multiple JSON fields named CAD – primo May 01 '19 at 12:54
  • So i've deleted the: @SerializedName("CAD") private String cad; syntax, and I am have to face a new error which is expected begin_array but was begin_object at line 1 column 2 path $ –  May 01 '19 at 12:57
  • 1
    so possibly what @M D is saying is correct – primo May 01 '19 at 13:01
  • How do i do that? –  May 01 '19 at 13:15

1 Answers1

1

As stated on website you might be getting this type of JSON response

{
  "base": "EUR",
  "date": "2018-04-08",
  "rates": {
    "CAD": 1.565,
    "CHF": 1.1798,
    "GBP": 0.87295,
    "SEK": 10.2983,
    "EUR": 1.092,
    "USD": 1.2234,
    ...
  }
}

So to parse this type of JSON your POJO class should look like this

public class MyPojo
{
    private String date;

    private Rates rates;

    private String base;

    public String getDate ()
    {
        return date;
    }

    public void setDate (String date)
    {
        this.date = date;
    }

    public Rates getRates ()
    {
        return rates;
    }

    public void setRates (Rates rates)
    {
        this.rates = rates;
    }

    public String getBase ()
    {
        return base;
    }

    public void setBase (String base)
    {
        this.base = base;
    }

    @Override
    public String toString()
    {
        return "ClassPojo [date = "+date+", rates = "+rates+", base = "+base+"]";
    }

public class Rates
{
    private String CHF;

    private String EUR;

    private String GBP;

    private String CAD;

    private String USD;

    private String SEK;

    public String getCHF ()
    {
        return CHF;
    }

    public void setCHF (String CHF)
    {
        this.CHF = CHF;
    }

    public String getEUR ()
    {
        return EUR;
    }

    public void setEUR (String EUR)
    {
        this.EUR = EUR;
    }

    public String getGBP ()
    {
        return GBP;
    }

    public void setGBP (String GBP)
    {
        this.GBP = GBP;
    }

    public String getCAD ()
    {
        return CAD;
    }

    public void setCAD (String CAD)
    {
        this.CAD = CAD;
    }

    public String getUSD ()
    {
        return USD;
    }

    public void setUSD (String USD)
    {
        this.USD = USD;
    }

    public String getSEK ()
    {
        return SEK;
    }

    public void setSEK (String SEK)
    {
        this.SEK = SEK;
    }

    @Override
    public String toString()
    {
        return "ClassPojo [CHF = "+CHF+", EUR = "+EUR+", GBP = "+GBP+", CAD = "+CAD+", USD = "+USD+", SEK = "+SEK+"]";
    }
}
}

Reference link

Let me know if it works

primo
  • 1,340
  • 3
  • 12
  • 40
  • So I,ve created new class called MyPojo (should I?) and I've changed my Currency class, as u advised. Program finally started, but i don't receive the values of currency. It's Look like "a:null". –  May 01 '19 at 14:45
  • did you make any changes in retrofit calling? If yes then please add your edited code so that I can help you – primo May 02 '19 at 04:15