Retrofit parse selective JSON data - android

I am parsing JSON data from this URL. Calling like this:
call.enqueue(new Callback<List<Gift>>() {
#Override
public void onResponse(Call<List<Gift>> call, Response<List<Gift>> response) {
List<Gift> places = response.body();
}
}
But I don't want this. I want to first check if the flag is 0. If it is, then I want to get only the values of the list key. And want to use the following model:
class Gift extends RealmObject{
String code, name;
//getters & setters
}
How can I achieve this?
Any help is highly appreciated.

Try this way sample
class GiftList{
String flag;
String flag1;
List<Gift> gifts;
}
call.enqueue(new Callback<List<GiftList>>() {
#Override
public void onResponse(Call<List<GiftList>> call, Response<List<GiftList>> response) {
List<GiftList> places = response.body();
if(places.getFlag().equals("0"){
List<Gift> gifts=places.getList();
}
}

You can create another POJO to store your Gift class, which store the outer value like flag and flag1, then you can access the flag to determine if you are going to go into list
here is how it looks like:
class GiftResponse extends RealmObject{
int flag;
String flag1;
Gift[] list;
//getters & setters
}
and keep your Gift class as it is, then you can get the data like:
call.enqueue(new Callback<GiftResponse>() {
#Override
public void onResponse(Call<GiftResponse> call, Response<GiftResponse> response) {
GiftResponse res = response.body();
if(res.getFlag() == 0) {
Gift[] arrGifts = res.getList();
}
}
}
ofcourse using this approach you change the call response type.

You can create a ResponseWrapper class as below:
public class ResponseWrapper<T> {
private T data;
#JsonProperty("flag")
public int flag;
#JsonProperty("flag1")
public String flag1;
public T getData() {
return data;
}
}
And modify your callback
call.enqueue(new Callback<ResponseWrapper<List<Gift>>>() {
#Override
public void onResponse(Call<ResponseWrapper<List<Gift>>> call, Response<ResponseWrapper<List<Gift>>> response) {
int flag = response.body().flag;
List<Gift> places = response.body().getData();
}
}

Related

Android Studio Retrofit OnResponse Problem

Im working on mvvm design but OnResponse is not saving the data in List. İts returning the emtpy List array. I cant reach the valued List. I realy dont know where is the incorrect piece of code. Here is the code.Help please.
public class RetroClass {
private static final String BASE_URL="--";
private List<ProductModel> productList=new ArrayList<>();
public static Retrofit getRetroInstance(){
return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
public static APIService getAPIService(){
return getRetroInstance().create(APIService.class);
}
public List<ProductModel> getProducts(){
APIService apiService=getAPIService();
apiService.getProducts().enqueue(new Callback<List<ProductModel>>() {
#Override
public void onResponse(Call<List<ProductModel>> call, Response<List<ProductModel>> response) {
productList.addAll(response.body());
for (int k=0;k<productList.size();k++) {
Log.d("onResponse: ", productList.get(k).getOrderName());//im getting the value here
}
}
#Override
public void onFailure(Call<List<ProductModel>> call, Throwable t) {
Log.d("onFailure: ",t.getMessage());
}
});
return productList;//but this is empty
}
}
Here is my view model.
public class ProductsVievModal extends ViewModel {
List<ProductModel> productList;
LiveData<List<ProductModel>> liveproductList;
RetroClass apiClass=new RetroClass();
public List<ProductModel> getProducts(){
productList=apiClass.getProducts();
for (int k=0;k<productList.size();k++) {
Log.d("onResponse: ", productList.get(k).getOrderName());
}
return productList;
}
}
.enqueue is asynchronously sending the request and notify callback of its response. It is asynchronous. onResponse() must complete before you return the product list.
I suspect the return productList; is executed before the onResponse() returned its value. Can you check by putting a log before return productList; to see which line is executed first?
Your data IS saved, but the moment your code needs it the .enqueue is probably not done retrieving the data yet. so it shows as empty
Easiest way to fix this is by having your follow up code in the onResponse so your basicly stuck waiting untill it either retrieved the information or failed
so something like this
public void onResponse(Call<List<ProductModel>> call, Response<List<ProductModel>> response) {
productList.addAll(response.body());
nextFunction();
}
}
#Override
public void onFailure(Call<List<ProductModel>> call, Throwable t) {
Log.d("onFailure: ",t.getMessage());
failFunction();
}
```

Can't make retrofit and Gson pull data from deployd

I am very new to Android development. I have this little project of mine that I need to get to work by accessing an api that I created locally on my mac with deployd. The api is accessible from localhost:2403/subjects. I have followed the retrofit and gson guide but so far I only keep errors and nothing viable to work with. At this point im kinda stuck. I need to get the subjects from the api and show them in a scrollable list.
I have set up Retrofit and Gson to be able to talk to the API. Therefore I have made a few classes and interfaces.
First the Subject class
public class Subject {
int id;
String name;
int ects;
int grade;
int period;
int main;
public int getMain() {
return main;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getEcts() {
return ects;
}
public int getGrade() {
return grade;
}
public int getPeriod() {
return period;
}
}
then I created a HslSubjects class which is plain and simple to hold all the subjects I get.
public class HslSubjects {
List<Subject> subjects;
}
and the api interface
public interface subjectEndpointApi {
#GET("/subjects")
Call<HslSubjects> loadSubjects();
}
followed by an adapter
public class SubjectResponse {
#SerializedName("subjects")
List<Subject> subjects;
public SubjectResponse() {
subjects = new ArrayList<Subject>();
}
public static SubjectResponse parseJSON(String response) {
Gson gson = new GsonBuilder().create();
SubjectResponse subjectResponse = gson.fromJson(response, SubjectResponse.class);
return subjectResponse;
}
}
Finally in my mainActivity I run everything
public class MainActivity extends ListActivity implements Callback<HslSubjects> {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_PROGRESS);
ArrayAdapter<Subject> arrayAdapter = new ArrayAdapter<Subject>(this, android.R.layout.simple_list_item_1, android.R.id.text1, new ArrayList<Subject>());
setListAdapter(arrayAdapter);
setProgressBarIndeterminateVisibility(true);
setProgressBarVisibility(true);
Log.i("api", "preparing to make the api call");
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://10.0.3.2:2403") //10.0.3.2
.addConverterFactory(GsonConverterFactory.create())
.build();
// preparing the call in retrofit
subjectEndpointApi subjectEndpointApi = retrofit.create(subjectEndpointApi.class);
Call<HslSubjects> call = subjectEndpointApi.loadSubjects();
call.enqueue(this);
}
#Override
public void onResponse(Call<HslSubjects> call, Response<HslSubjects> response) {
setProgressBarIndeterminateVisibility(false);
HslSubjects hslSubjects = response.body();
Log.i("subjects", "end of response");
}
#Override
public void onFailure(Call<HslSubjects> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
Log.i("subjects", "Oops error");
}
}
But somehow it always goes to the onFailure class. The emulator gives the following error:
Seems like your server JSON is not what you are expecting on your device.
Error says that android wants JSON object, but the json you pass is kinda array.
Try to add logging and see what is the problem there.
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
So I guess you should write something like:
public interface subjectEndpointApi {
#GET("/subjects")
Call<List<Subject>> loadSubjects();
}

ActiveAndroid - How to save data into Android database

I have an Android app in which I'm getting data from an API. Now I need to save this data from the API into an ActiveAndroid table.
So I've got stuck on that part.
Here is my table Partners(Active Android):
#Table(name = "Partners")
public class Partners extends Model {
#Column(name = "Name")
public String name;
public Partners() {}
public Partners(String name) {
this.name = name;
}
}
This is my POJO model:
public class Partner {
#Expose
#Column(name = "name")
private List<String> name;
public List<String> getName() {
return name;
}
public void setName(List<String> name) {
this.name = name;
}
}
And here is part of code where I'm getting data and trying to save it into ActiveAndroid table:
public class DownloadMain extends Fragment implements Callback<Partner> {
private static final String TAG = DownloadMain.class.getSimpleName();
private Button dloadPartners;
private Call callPartners;
public DownloadMain() {}
public DownloadMain newInstance() { return new DownloadMain(); }
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.download_main, container, false);
dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
dloadPartners.setOnClickListener(btnListener);
callPartners = APIHelper.getApiService().getPartners();
return view;
}
Button.OnClickListener btnListener = (new Button.OnClickListener() {
#Override
public void onClick(View v) {
callPartners.clone().enqueue(DownloadMain.this);
insertPartners();
}
});
#Override
public void onResponse(Call call, Response response) {
if(response.body() == null) {
try {
response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getActivity(), "No Partners!", Toast.LENGTH_SHORT).show();
} else {
List<String> partners = (List<String>) response.body();
Log.d(TAG, "Number of partners received: " + partners.size());
Toast.makeText(getActivity(), "Partners downloaded!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call call, Throwable t) {
}
private void insertPartners() {
ActiveAndroid.beginTransaction();
try {
for (int i = 0; i < 100; i++) {
Partner partner = new Partner();
partner.getName();
//partner.save();
}
ActiveAndroid.setTransactionSuccessful();
} finally {
ActiveAndroid.endTransaction();
}
}
}
The problem is how to save data I get from the API into table, so I need few tips and advice how to properly do that.
Question: I need some tips how to save data I get from web with retrofit into ActiveAndroid table?
please check my old weather app project, where I'f already used ActiveAndroid.
Here's one of my saving to database methods:
public void saveCityDataToDatabase(Forecast forecast) {
ActiveAndroid.beginTransaction();
try {
if (WeatherApplication.getCityList().size() > 0) {
new Delete().from(City.class).execute();
}
forecast.getCity().getCoord().save();
forecast.getCity().save();
ActiveAndroid.setTransactionSuccessful();
} finally {
ActiveAndroid.endTransaction();
}
Log.d("DATABASE", "WeatherApplication: " + WeatherApplication.getCityList());
} }
From: https://github.com/piotrek1543/LocalWeather/blob/master/app/src/main/java/com/piotr/localweather/repositories/WeatherDatabaseRepository.java
With ActiveAndroid is really easy to save Objects like Weather or Wind, but for some purposes you would need to use TypeSerializer. In your example you would use it to deserialize and save List<String>.
As you may notice from its Github page: https://github.com/pardom/ActiveAndroid
this libary is not maintained more than two years, so I can say clearly that is deprecated and not good to use to fresh projects. It may have many bugs. For me, implementation of this lib was a pretty painful.
Instead of ActiveAndroid, I would recommend you to use Realm, greenDao or ORMLite library to store your data.
Hope it would help
First of all create a parameterless constructor and call super in it.
public Partners() {
super();
}
then a partern.save() should suffice.
To retreive all the parterns you could do something like
List<Partner> partners = new Select().from(Partner.class).execute());
if you get the Partner object fro web via retrofit, probably you are using Gson to put the json in partner object. so you can make that object extending model, put a paramterless constructor like above and put a #Table annotation.

How to get JSON array from web api with retrofit and active android

I have an web api which gives me array of partners and it looks like this:
[
"partner1",
"partner2",
"partner3",
"....",
"parner222"
]
I have Table partners (ActiveAndroid) in which I would like to save all partners from api.
#Table(name = "Partners")
public class Partners extends Model {
#Column(name = "Name")
String name;
public Partners() {}
public Partners(String name) {
this.name = name;
}
}
Here is my Pojo model class:
public class Partners {
#SerializedName("name")
#Expose
private List<String> name = new ArrayList<String>();
public List<String> getName() {
return name;
}
public void setName(List<String> name) {
this.name = name;
}
}
This is my interface
public interface APIService {
#GET("Partners")
Call<Partners> getPartners();
}
And this is my APIHelper with api url
public class APIHelper {
public static APIService apiService;
public static APIService getApiService() {
if (apiService == null) {
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://part-oflink.domain.com/partners.json/")
.addConverterFactory(GsonConverterFactory.create()).build();
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}
And this is Fragment where I have an Button on which I would like to implement onClick method to get data from API and save it into Partners table.
public class DownloadMain extends Fragment implements Callback<Partners> {
private Button dloadPartners;
private Call<Partners> callPartners;
public static APIService apiService;
public DownloadMain() {}
public DownloadMain newInstance() { return new DownloadMain(); }
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.download_main, container, false);
dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
dloadPartners.setOnClickListener(btnListener);
callPartners = APIHelper.getApiService().getPartners();
callPartners.enqueue(this);
return view;
}
Button.OnClickListener btnListener = (new View.OnClickListener() {
#Override
public void onClick(View v) {
//here I need to implement that on click downloads me data
// and save it into my Partners table
}
});
#Override
public void onResponse(Call<Partners> call, Response<Partners> response) {
//here I'm trying to put api response into array list
if (response.body() != null) {
ArrayList<String> partnersList = new ArrayList<>();
partnersList = response.body();
}
}
#Override
public void onFailure(Call<Partners> call, Throwable t) {
}
}
And now I have stuck. I would like to implement onClick Button method to get data from API. In onResponse() method I'm trying to put data into ArrayList to check if data is recieved. And also I would like to save this data into my table partners.
I would be grateful if someone could help me or guide me to fix this. This is first time I'm doing with retrofit and api.
Can somebody help me or guide me to successfully get data from API and save it into table Partners?
The way you are trying to parse the JSON string(array of partners) is not the appropriate. Your JSON should like this:
{
"partners":
["partner1", "partner2", "partner3", ...]
}
And the POJO model class should be:
class Partners{
private List<String> partners;
public Partners(){}
public void setList(List<String> partners) {
this.partners = partners;
}
public List<String> getList() {
return this.partners;
}
//setter and getter methods
}
If the response is not empty then for printing the values:
for(Partner partner: response){
Log.d("Partner Name",partner.name);
}
And if you are using any ORM for the database, then call its DAO and pass the values to save in the DB.

Is there a way to use retrofit with POJO's setters?

I have a REST API and i use Retrofit library for calling request.
For exmaple i have a some POJO (Dialog.java):
public class Dialog {
#Expose
#SerializedName("dialogId")
private int _id;
#Expose
private String opponentLogin;
public void setOpponentLogin(String opponentLogin) {
// these should be some magic with opponentLogin before it can be saved in memory
this.opponentLogin = opponentLogin;
}
public String getOpponentLogin() {
return opponentLogin;
}
}
And some call method from my ApiManager:
public void getDialogList() {
Call<List<Dialog>> call = service.getDialogList();
call.enqueue(new Callback<List<Dialog>>() {
#Override
public void onResponse(Response<List<Dialog>> response) {
switch (response.code()) {
case 200:
// work with POJO object
break;
}
}
#Override
public void onFailure(Throwable t) {
// TODO no internet connection
}
});
}
The question is: can i call setOpponentLogin method (and some other setter) when retrofit convert JSON answer to POJO?
Yes, you can do this with setter methods. Setter methods is used for uploading some contents to API like some text and images. It depends upon your API whether to use raw JSON body or something else.

Categories

Resources