Java – Android, which displays JSON data in applications

Android, which displays JSON data in applications… here is a solution to the problem.

Android, which displays JSON data in applications

I

have this JSON data and I tried to show the “Measure” section but it doesn’t work.

(I get this: java.lang.IllegalStateException: Expected BEGIN_OBJECT but be BEGIN_ARRAY at line 1 column 2 path $).

I’m a beginner in Android development, this is my first app, I just don’t know how to fix this.

Here is JSON:

[{
"id":1,
"type":"TEMPERATURE",
"measurements":[
    {
        "value":"22.58",
        "time":"2017-01-11T12:20:44.701"
        }]
},{
"id":2,
"type":"HUMIDITY",
"measurements":[
    {
        "value":"52.366",
        "time":"2017-01-11T12:20:44.731"
        }]
},{
"id":3,
"type":"LUMINOSITY",
"measurements":[
    {
        "value":"1.0",
        "time":"2017-01-11T12:20:44.742"
        }]
}]

Adapter:

public class SenzoriAdapter extends RecyclerView.Adapter < SenzoriAdapter.ViewHolder > {

private ArrayList < Measurement > mSenzori;

public SenzoriAdapter(ArrayList < Measurement > senzori) {
        this.mSenzori = senzori;
    }

@Override
    public SenzoriAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.main_item, viewGroup, false);
        return new ViewHolder(view);
    }

@Override
    public void onBindViewHolder(SenzoriAdapter.ViewHolder viewHolder, int i) {
        String datum = mSenzori.get(i).getTime().replace("T", "  ");
        viewHolder.senzoriLastAlive.setText(datum);
        String stringdouble = Double.toString(mSenzori.get(i).getValue());
        viewHolder.senzoriMeasurement.setText(stringdouble);

}

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

public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView senzoriLastAlive, senzoriMeasurement;
        public ViewHolder(View itemView) {
            super(itemView);
            senzoriLastAlive = (TextView) itemView.findViewById(R.id.senzoriLastAlive);
            senzoriMeasurement = (TextView) itemView.findViewById(R.id.senzoriMeasurement);
        }
    }
}

Model Senzori :

public class Senzori {

@Expose
    private Integer id;
    @Expose
    private String type;
    @Expose
    private Measurement[] measurements;

public Integer getId() {
        return id;
    }

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

public String getType() {
        return type;
    }

public void setType(String type) {
        this.type = type;
    }

public Measurement[] getMeasurement() {
        return measurements;
    }
}

Model Measurement:

public class Measurement {

@Expose
    private Double value;
    @Expose
    private String time;

public Double getValue() {
        return value;
    }

public void setValue(Double value) {
        this.value = value;
    }

public String getTime() {
        return time;
    }

public void setTime(String time) {
        this.time = time;
    }

}

and usage in Activity:

public void configViews() {
    mRecyclerView = (RecyclerView) findViewById(recyclerView);
    mRecyclerView.setHasFixedSize(true);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    mRecyclerView.setLayoutManager(layoutManager);
    loadJSON();
}

public void loadJSON() {
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(MainActivity.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    SenzoriInterface request = retrofit.create(SenzoriInterface.class);
    Call < Senzori > call = request.getAllSenzori(MainActivity.BASE_URL + "/sensors/");
    call.enqueue(new Callback < Senzori > () {
        @Override
        public void onResponse(Call < Senzori > call, Response < Senzori > response) {

Senzori jsonResponse = response.body();
            senzori = new ArrayList < > (Arrays.asList(jsonResponse.getMeasurement()));
            senzoriAdapter = new SenzoriAdapter(senzori);
            mRecyclerView.setAdapter(senzoriAdapter);
        }

@Override
        public void onFailure(Call < Senzori > call, Throwable t) {
            Log.d("Error", t.getMessage());
        }
    });
}

Solution

You expect an object, but the response is to give you an array of objects.

Change

Call<Senzori> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");

to

Call<List<Senzori>> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");

and update your code accordingly.

call.enqueue(new Callback<List<Senzori>>() {
    @Override
    public void onResponse(Call<List<Senzori>> call, Response<List<Senzori>> response) {

senzori = response.body();
        senzoriAdapter = new SenzoriAdapter(senzori.getMeasurement());
        mRecyclerView.setAdapter(senzoriAdapter);
    }

@Override
    public void onFailure(Call<List<Senzori>> call, Throwable t) {
        Log.d("Error",t.getMessage());
    }
});

Related Problems and Solutions