Jacek
Jacek

Reputation: 45

JSON (POJO) model response

I have a problem with response model for my JSON.

I'm working with hitbtc API: https://api.hitbtc.com/api/2/public/currency.

When I convert this file to POJO model, I Have only this file:

public class Currency {

@SerializedName("id")
@Expose
private String id;
@SerializedName("fullName")
@Expose
private String fullName;
@SerializedName("crypto")
@Expose
private Boolean crypto;
@SerializedName("payinEnabled")
@Expose
private Boolean payinEnabled;
@SerializedName("payinPaymentId")
@Expose
private Boolean payinPaymentId;
@SerializedName("payinConfirmations")
@Expose
private Integer payinConfirmations;
@SerializedName("payoutEnabled")
@Expose
private Boolean payoutEnabled;
@SerializedName("payoutIsPaymentId")
@Expose
private Boolean payoutIsPaymentId;
@SerializedName("transferEnabled")
@Expose
private Boolean transferEnabled;
@SerializedName("delisted")
@Expose
private Boolean delisted;
@SerializedName("payoutFee")
@Expose
private String payoutFee;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getFullName() {
    return fullName;
}

public void setFullName(String fullName) {
    this.fullName = fullName;
}

public Boolean getCrypto() {
    return crypto;
}

public void setCrypto(Boolean crypto) {
    this.crypto = crypto;
}

public Boolean getPayinEnabled() {
    return payinEnabled;
}

public void setPayinEnabled(Boolean payinEnabled) {
    this.payinEnabled = payinEnabled;
}

public Boolean getPayinPaymentId() {
    return payinPaymentId;
}

public void setPayinPaymentId(Boolean payinPaymentId) {
    this.payinPaymentId = payinPaymentId;
}

public Integer getPayinConfirmations() {
    return payinConfirmations;
}

public void setPayinConfirmations(Integer payinConfirmations) {
    this.payinConfirmations = payinConfirmations;
}

public Boolean getPayoutEnabled() {
    return payoutEnabled;
}

public void setPayoutEnabled(Boolean payoutEnabled) {
    this.payoutEnabled = payoutEnabled;
}

public Boolean getPayoutIsPaymentId() {
    return payoutIsPaymentId;
}

public void setPayoutIsPaymentId(Boolean payoutIsPaymentId) {
    this.payoutIsPaymentId = payoutIsPaymentId;
}

public Boolean getTransferEnabled() {
    return transferEnabled;
}

public void setTransferEnabled(Boolean transferEnabled) {
    this.transferEnabled = transferEnabled;
}

public Boolean getDelisted() {
    return delisted;
}

public void setDelisted(Boolean delisted) {
    this.delisted = delisted;
}

public String getPayoutFee() {
    return payoutFee;
}

public void setPayoutFee(String payoutFee) {
    this.payoutFee = payoutFee;
}

}

In the next step I want to get list of items, seems like here:

 public class CurrencyResponse {
@SerializedName("page")
private int page;
@SerializedName("results")
private List<Currency> results;
@SerializedName("total_results")
private int totalResults;
@SerializedName("total_pages")
private int totalPages;

public int getPage() {
    return page;
}

public void setPage(int page) {
    this.page = page;
}

public List<Currency> getResults() {
    return results;
}

public void setResults(List<Currency> results) {
    this.results = results;
}

public int getTotalResults() {
    return totalResults;
}

public void setTotalResults(int totalResults) {
    this.totalResults = totalResults;
}

public int getTotalPages() {
    return totalPages;
}

public void setTotalPages(int totalPages) {
    this.totalPages = totalPages;
}
}

When I'm trying to make Adapter and display my list of currencies (for now I need the only name of currencies in listview), I've received nullPointException.

I know that somewhere I make a categorical mistake, but I still have little experience in RESTfull API.

If you have any tips and you could help me, I will be very glad.

EDIT: CurrenciesAdapter.java:

public class CurrenciesAdapter extends 
RecyclerView.Adapter<CurrenciesAdapter.CurrencyViewHolder> {

private List<Currency> currencies;
private int rowLayout;
private Context context;


public static class CurrencyViewHolder extends RecyclerView.ViewHolder {
    LinearLayout currenciesLayout;
    TextView currencyTitle;
    TextView data;
    TextView currencyDescription;
    TextView rating;


    public CurrencyViewHolder(View v) {
        super(v);
        currenciesLayout = (LinearLayout) v.findViewById(R.id.currencies_layout);
        currencyTitle = (TextView) v.findViewById(R.id.title);
        data = (TextView) v.findViewById(R.id.subtitle);
        currencyDescription = (TextView) v.findViewById(R.id.description);
        //rating = (TextView) v.findViewById(R.id.rating);
    }
}

public CurrenciesAdapter(List<Currency> currencies, int rowLayout, Context context) {
    this.currencies = currencies;
    this.rowLayout = rowLayout;
    this.context = context;
}

@Override
public CurrenciesAdapter.CurrencyViewHolder onCreateViewHolder(ViewGroup parent,
                                                            int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
    return new CurrencyViewHolder(view);
}


@Override
public void onBindViewHolder(CurrencyViewHolder holder, final int position) {
    holder.currencyTitle.setText(currencies.get(position).getFullName());
    holder.data.setText(currencies.get(position).getPayoutFee());
    if(currencies.get(position).getPayinEnabled()== true) {
        holder.currencyDescription.setText("true");
    }
    else holder.currencyDescription.setText("false");
   // holder.rating.setText(currencies.get(position).getVoteAverage().toString());
}

@Override
public int getItemCount() {
    return currencies.size();
}
}

MainActivity.java:

   public class MainActivity extends AppCompatActivity {

   private static final String TAG = MainActivity.class.getSimpleName();


// TODO - insert your themoviedb.org API KEY here
private final static String API_KEY = "My_key";


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

    if (API_KEY.isEmpty()) {
        Toast.makeText(getApplicationContext(), "Please obtain your API KEY from hitbtc.com first!", Toast.LENGTH_LONG).show();
        return;
    }

    final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.movies_recycler_view);
    LinearLayoutManager manager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(manager);
    recyclerView.setHasFixedSize(true);



    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);

    Call<CurrencyResponse> call = apiService.getCurrencies(API_KEY);
    call.enqueue(new Callback<CurrencyResponse>() {
        @EverythingIsNonNull
        public void onResponse(Call<CurrencyResponse> call, Response<CurrencyResponse> response) {
            int statusCode = response.code();
            List<Currency> currencies = response.body().getResults();
            recyclerView.setAdapter(new CurrenciesAdapter(currencies, R.layout.list_item_currency, getApplicationContext()));
        }

        @Override
        public void onFailure(Call<CurrencyResponse> call, Throwable t) {
            // Log error here since request failed
            Log.e(TAG, t.toString());
        }
    });
}
}

I have NPE in 63 line in MainActivity.

Logcat:

  --------- beginning of crash
  2019-03-11 13:58:12.020 3325-3325/com.example.mojpierwszyrest 
  E/AndroidRuntime: FATAL EXCEPTION: main
  Process: com.example.mojpierwszyrest, PID: 3325
  java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.example.mojpierwszyrest.model.CurrencyResponse.getResults()' on a null object reference
    at com.example.mojpierwszyrest.acitivity.MainActivity$1.onResponse(MainActivity.java:63)
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:71)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    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)
    2019-03-11 13:58:12.563 3325-3325/com.example.mojpierwszyrest I/Process: 
    Sending signal. PID: 3325 SIG: 9

Upvotes: 0

Views: 226

Answers (1)

Birju Vachhani
Birju Vachhani

Reputation: 6353

I checked the above link you provided in the description and I came to know that there's an array in response. so according to that you shouldn't need CurrencyResponse class. Just Currency class is enough.

In your retrofit interface, the api method should return list of currency. e.g. List<Currency> getCurrencyList(). It should work.

For NPE, probable cause should be that you are trying to access a field from these classes which is not in the api response so that the field will be null and accessing that will throw NPE. You can check stacktrace to find out which field access is throwing NPE or you can share stacktrace so that this community can help you.

Upvotes: 2

Related Questions