Android JSON parsing Retrofit - java

I'm new to Retrofit and JSON and I don't really know how to parse the next json string:
{
"weight":[
{ "bmi":21,
"date":"2016-12-09",
"fat":14.059000015258789,
"logId":1222222222222,
"source":"Aria",
"time":"11:58:24",
"weight":68
},
{ "bmi":21.83,
"date":"2016-12-14",
"logId":1222222222223,
"source":"Aria",
"time":"14:31:39",
"weight":70.7
}
]
}
I just want "weight" and "date" inside weight array. I've created a pojo class following some examples but it's not working.
Also when trying it with my pojo class I couldn't get "weight" as a string (I'll then use it as a double) using .string().
(I know using .toString() shows something like "com.myPackage.MyPojo#xxxx").
For now, I have only been able to get the whole json through ResponseBody:
Call<ResponseBody>call = repository.getFitbitApi().getData();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
What am I doing wrong? Here are my pojo classes, just an attempt...:
public class WeightList {
#SerializedName("weight")
#Expose
private ArrayList<WeightLogFitbit> weight = new ArrayList<>();
public WeightList(){
}
public ArrayList<WeightLogFitbit> getWeight() {
return weight;
}
public void setWeight(ArrayList<WeightLogFitbit> weight) {
this.weight = weight;
}
}
And:
public class WeightLogFitbit {
//Variables in my JSON
#SerializedName("bmi")
#Expose
private String bmi;
#SerializedName("date")
#Expose
private String date;
#SerializedName("logId")
#Expose
private String logId;
#SerializedName("source")
#Expose
private String source;
#SerializedName("time")
#Expose
private String time;
#SerializedName("weight")
#Expose
private double weight;
#SerializedName("fat")
#Expose
private String fat;
public WeightLogFitbit(){}
//Getters and setters
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getBmi(){
return bmi;
}
public void setBmi(String bmi) {
this.bmi = bmi;
}
//
public String getFat(){
return fat;
}
public void setFat(String fat) {
this.fat = fat;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getLogId() {
return logId;
}
public void setLogId(String logId) {
this.logId = logId;
}
}
NOTE: I'm using RxSocialConnect library, which implements RxJava, Retrofit 2, OkHttp3 and gson, just in case. I did this following this example.
Rest of classes I'm using:
public class FitbitBtnActivity extends AppCompatActivity {
private FitbitRepository repository;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fitbit_btn);
repository = new FitbitRepository();
setUpFitbit();
}
private void setUpFitbit() {
findViewById(R.id.fitbitbtn).setOnClickListener(v ->
RxSocialConnect.with(this, repository.fitbitService())
.subscribe(response -> response.targetUI().showToken(response.token()),
error -> showError(error))
);
findViewById(R.id.retrievebtn).setOnClickListener(v -> {
Call<ResponseBody>call = repository.getFitbitApi().getData();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
//Original code from example in RxSocialConnect
/*.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
#Override
public void call(Object user) {
FitbitBtnActivity.this.showUserProfile(user.toString());
}
},
error -> FitbitBtnActivity.this.showError(error));*/
}
);
}
And:
public class FitbitRepository {
private final FitbitApiRest fitbitApi;
public FitbitRepository() {
fitbitApi = initFitbitApiRest();
}
private FitbitApiRest initFitbitApiRest() {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth2Interceptor(FitbitApi20.class))
.build();
return new Retrofit.Builder()
.baseUrl(FitbitApiRest.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(FitbitApiRest.class);
}
FitbitApiRest getFitbitApi() {
return fitbitApi;
}
interface FitbitApiRest {
String URL_BASE = "https://api.fitbit.com";
#GET("myrequest.json")
Call<ResponseBody> getData();
}
OAuth20Service fitbitService() {
final String client_id = "xxxxx";
final String client_secret = "1xxxxxxxxxxxxxxxxxx";
final String redirect_uri = "http://example.com";
final String permissions = "weight";
return new ServiceBuilder()
.apiKey(client_id)
.apiSecret(client_secret)
.callback(redirect_uri)
.scope(permissions)
.build(FitbitApi20.instance());
}
}

You need to add this to your dependencies:
compile 'com.squareup.retrofit2:converter-gson:your-version'
and then add a gson converter to your Retrofit instance like this:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
and change your call in the api to return WeightList:
Call<WeightList> getData();

Related

I want to add a bearer token to my retrofit post request

I have an app that is to register people into a platform but I get a response of Unauthenticated each time I submit the form data. The form is submitted using an API which requires a bearer token for each post request with the aid of retrofit. I have been out of touch with Java.
Note: its just a plain form. No authentication has been implemented in the app.
My ApiClient.java class
public class ApiClient {
private static Retrofit getRetrofit(){
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("xxxxxxxxxxxxx")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
return retrofit;
}
public static UserService getUserService(){
UserService userService = getRetrofit().create(UserService.class);
return userService;
}
}
My UserService.java class
public interface UserService {
#POST("algonapi/api/enroll_vehicle")
Call<UserResponse> saveUser(#Body UserRequest userRequest);
}
My saveUser Method
public void saveUser(UserRequest userRequest){
Call<UserResponse> userResponseCall = ApiClient.getUserService().saveUser(userRequest);
userResponseCall.enqueue(new Callback<UserResponse>() {
#Override
public void onResponse(Call<UserResponse> call, Response<UserResponse> response) {
if (response.isSuccessful()){
Toast.makeText(MainActivity.this, "Registration Successfull! Click on Reset Form to Start a New Enumeration...", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(MainActivity.this, "Registration Failed!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<UserResponse> call, Throwable t) {
Toast.makeText(MainActivity.this, "Registration Failed!" +t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
});
}
My UserRequest
package com.example.xxxxx;
public class UserRequest {
private String FullName;
private String StickerNumber;
private String Address;
private String Email;
private String Phone;
private String Nationality;
private String State;
private String LGA;
private String RC;
private String DriversLicenseNo;
private String LicenseIssued;
private String LicenseExpiry;
private String VehicleType;
private String VehicleLicense;
private String VehicleTyres;
private String LGAofOperation;
private String NOKFullName;
private String NOKAddress;
private String NOKPhone;
private String NOKEmail;
private String NOKNationality;
private String NOKState;
public String getFullName() {
return FullName;
}
public void setFullName(String fullName) {
FullName = fullName;
}
public String getStickerNumber() {
return StickerNumber;
}
public void setStickerNumber(String stickerNumber) {
StickerNumber = stickerNumber;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getPhone() {
return Phone;
}
public void setPhone(String phone) {
Phone = phone;
}
public String getNationality() {
return Nationality;
}
public void setNationality(String nationality) {
Nationality = nationality;
}
public String getState() {
return State;
}
public void setState(String state) {
State = state;
}
public String getLGA() {
return LGA;
}
public void setLGA(String LGA) {
this.LGA = LGA;
}
public String getRC() {
return RC;
}
public void setRC(String RC) {
this.RC = RC;
}
public String getDriversLicenseNo() {
return DriversLicenseNo;
}
public void setDriversLicenseNo(String driversLicenseNo) {
DriversLicenseNo = driversLicenseNo;
}
public String getLicenseIssued() {
return LicenseIssued;
}
public void setLicenseIssued(String licenseIssued) {
LicenseIssued = licenseIssued;
}
public String getLicenseExpiry() {
return LicenseExpiry;
}
public void setLicenseExpiry(String licenseExpiry) {
LicenseExpiry = licenseExpiry;
}
public String getVehicleType() {
return VehicleType;
}
public void setVehicleType(String vehicleType) {
VehicleType = vehicleType;
}
public String getVehicleLicense() {
return VehicleLicense;
}
public void setVehicleLicense(String vehicleLicense) {
VehicleLicense = vehicleLicense;
}
public String getVehicleTyres() {
return VehicleTyres;
}
public void setVehicleTyres(String vehicleTyres) {
VehicleTyres = vehicleTyres;
}
public String getLGAofOperation() {
return LGAofOperation;
}
public void setLGAofOperation(String LGAofOperation) {
this.LGAofOperation = LGAofOperation;
}
public String getNOKFullName() {
return NOKFullName;
}
public void setNOKFullName(String NOKFullName) {
this.NOKFullName = NOKFullName;
}
public String getNOKAddress() {
return NOKAddress;
}
public void setNOKAddress(String NOKAddress) {
this.NOKAddress = NOKAddress;
}
public String getNOKPhone() {
return NOKPhone;
}
public void setNOKPhone(String NOKPhone) {
this.NOKPhone = NOKPhone;
}
public String getNOKEmail() {
return NOKEmail;
}
public void setNOKEmail(String NOKEmail) {
this.NOKEmail = NOKEmail;
}
public String getNOKNationality() {
return NOKNationality;
}
public void setNOKNationality(String NOKNationality) {
this.NOKNationality = NOKNationality;
}
public String getNOKState() {
return NOKState;
}
public void setNOKState(String NOKState) {
this.NOKState = NOKState;
}
}
Create the OkHttpClient like this
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#NotNull
#Override
public Response intercept(#NotNull Chain chain) throws IOException {
Request request=chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + token)
.build();
return chain.proceed(request);
}
}).build();
If you most of your https requests need authentication then the first answer is perfect but if some of your requests need then you can pass the header to each methods.
public interface UserService {
#POST("algonapi/api/enroll_vehicle")
Call<UserResponse> saveUser(
#Header("Authorization") String token,
#Body UserRequest userRequest
);
}
While calling the method simply pass your token along with userRequest.

Retrofit response returning null in Android Studio

I want to fetch live data from coinbase api. I'm using Retrofit to make API call I got a null response when i tried returning displaying the data
the json response from the api
JSON
{"data":{"base":"BTC","currency":"USD","amount":"9510.915"}}
The retrofit class for the returned data
RETROFIT
myC2C = RetrofitClient.getInstance("https://api.coinbase.com/v2/prices/").create(IMyC2C.class);
Call<DataList> call = myC2C.getPrice("USD");
call.enqueue(new Callback<DataList>() {
#Override
public void onResponse(Call<DataList> call, Response<DataList> response) {
if (!response.isSuccessful()){
usd_price.setText("Code: " + response.code());
return;
}
Log.d("resedatasync", new Gson().toJson(response.body().getDatas()));
}
#Override
public void onFailure(Call<DataList> call, Throwable t) {
usd_price.setText(t.getMessage());
}
The endpoint that calls get methods and parse the type of currency
ENDPOINT
#GET("spot")
Call<DataList> getPrice(#Query("currency") String currency);
the java model class here
**JAVA CLASS
import java.util.List;
public class DataList {
private Datas Datas;
public Datas getDatas() {
return Datas;
}
public void setDatas(Datas datas) {
this.Datas = datas;
}
}
package com.example.c2c.Model;
public class Datas {
private String base;
private String currency;
private float amount;
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
}
**

retrofit returning object params out of order, with # sign and quotes

I'm using retrofit to send a call to an api to post an issue in a bug-tracker through my android app. The API needs it formatted a specific way, so I created a custom object to pass as a parameter. Unfortunately when I'm sending the request to the API its formatting it incorrectly. It alphabetizes the parameters, puts quotes around both the keys and the values, and adds an # to the beginning of my data, leading the API to not be able to make sense of what I'm trying to post. The format I'm looking to send is:
{ fb_user_id: dummyUID,
email: dummy#email.com,
first_name: John,
last_name: Smith,
project: android,
type: bug,
subject: title,
description: description }
Instead of the above, my api is receiving the data as
#"description":"description",
"email":"dummy#email.com",
"fb_user_id":"dummyUID",
"first_name":"John",
"last_name":"Smith",
"project":"android",
"subject":"title",
"type":"bug"
I'm using retrofit to do so, with my interface looking like
public interface MyAPI {
#POST("/op_create_ticket")
Observable<JsonElement> createTicket(#Body Ticket ticket);
}
And my activity calling it looking like:
public class HelpActivity extends BaseActivity {
#BindView(R.id.textView)
TextView textView;
#BindView(R.id.spinner)
Spinner spinner;
#BindView(R.id.email)
EditText email;
#BindView(R.id.firstName)
EditText firstName;
#BindView(R.id.lastName)
EditText lastName;
#BindView(R.id.subject)
EditText title;
#BindView(R.id.description)
EditText description;
#BindView(R.id.button3)
Button button3;
FirebaseAuth fbauth = FirebaseAuth.getInstance();
FirebaseUser user = fbauth.getCurrentUser();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
ButterKnife.bind(this);
}
#OnClick(R.id.button3)
public void onViewClicked() {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl("https://my.url");
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
builder.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
MyAPI api = retrofit.create(TriggerWatchAPI.class);
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
api.createTicket(ticket).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});
}
}
I'm wondering if there's any kind of converter or something that can convert my object to the kind of data the API is looking for.
edit: forgot to add my custom pojo
package watch.trigger.Model;
public class Ticket {
private String project;
private String first_name;
private String email;
private String description;
private String subject;
private String last_name;
private String fb_user_id;
private String type;
public String getProject ()
{
return project;
}
public void setProject (String project)
{
this.project = project;
}
public String getFirst_name ()
{
return first_name;
}
public void setFirst_name (String first_name)
{
this.first_name = first_name;
}
public String getEmail ()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public String getSubject ()
{
return subject;
}
public void setSubject (String subject)
{
this.subject = subject;
}
public String getLast_name ()
{
return last_name;
}
public void setLast_name (String last_name)
{
this.last_name = last_name;
}
public String getFb_user_id ()
{
return fb_user_id;
}
public void setFb_user_id (String fb_user_id)
{
this.fb_user_id = fb_user_id;
}
public String getType ()
{
return type;
}
public void setType (String type)
{
this.type = type;
}
#Override
public String toString()
{
return "ClassPojo [project = "+project+", first_name = "+first_name+", email = "+email+", description = "+description+", subject = "+subject+", last_name = "+last_name+", fb_user_id = "+fb_user_id+", type = "+type+"]";
}
}
don't send a custom object, send a JSON object as a String and in the API receive it as a JSON object.
first add this in your gradle:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
1- change this
public interface MyAPI {
#Headers("Content-Type: application/json")
#POST("/op_create_ticket")
Observable<JsonElement> createTicket(#Body Ticket ticket);
}
to :
public interface MyAPI {
#POST("/op_create_ticket")
Observable<String> createTicket(#Body String ticket);
}
2- change this
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
api.createTicket(ticket).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});
to
JSONObject tickenJson= new JSONObject();
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
ticketJson.put("fb_user_id",user.getUid());
ticketJson.put("email",email.getText().toString());
ticketJson.put("first_name",firstName.getText().toString());
ticketJson.put("last_name",lastName.getText().toString());
ticketJson.put("project","android");
ticketJson.put("type","design");
ticketJson.put("type",title.getText().toString());
ticketJson.put("description",description.getText().toString());
api.createTicket(ticketJson.toString()).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});

Android - unable to fetch JSON using Retrofit2

I'm trying to get a JSON file using an URL, but the application is crashing.
JSON file api
MainActivity.java
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService service = retrofit.create(ApiService.class);
// Logs show error is in the code below
service.getPopulationData(new Callback<Flag> (){
#Override
public void onResponse(Call<Flag> call, Response<Flag> response) {
Log.d("JSONData", response.body().toString());
}
#Override
public void onFailure(Call<Flag> call, Throwable t) {
Log.d("JSONData", t.getMessage());
}
});
ApiService.java
public interface ApiService {
String BASE_URL = "http://www.androidbegin.com/";
#GET("tutorial/jsonparsetutorial.txt")
public void getPopulationData(Callback<Flag> callback) ;
}
Flag.java
public class Flag {
private int rank;
private String country;
private String population;
private String flag;
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPopulation() {
return population;
}
public void setPopulation(String population) {
this.population = population;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
Edit: Error log can be found here: log
I've tried other solutions mentioned on stackoverflow, but I've been unable to get it right.
Also, I only want the flag URLs from the JSON file. How am I supposed to get it?
You will need the following two pojo class
JsonResponse.java
public class JsonResponse {
#SerializedName("worldpopulation")
#Expose
private List<Worldpopulation> worldpopulation = null;
public List<Worldpopulation> getWorldpopulation() {
return worldpopulation;
}
public void setWorldpopulation(List<Worldpopulation> worldpopulation) {
this.worldpopulation = worldpopulation;
}
}
Worldpopulation.java
public class Worldpopulation {
#SerializedName("rank")
#Expose
private Integer rank;
#SerializedName("country")
#Expose
private String country;
#SerializedName("population")
#Expose
private String population;
#SerializedName("flag")
#Expose
private String flag;
public Integer getRank() {
return rank;
}
public void setRank(Integer rank) {
this.rank = rank;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPopulation() {
return population;
}
public void setPopulation(String population) {
this.population = population;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
and make a retrofit call like below
service.getPopulationData(new Callback<JsonResponse> (){
#Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
Log.d("JSONData", response.body().toString());
ArrayList<Worldpopulation> population=new ArrayList(response.body().getWorldpopulation());
}
#Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
Log.d("JSONData", t.getMessage());
}
});
**** edited as per requirement ****
and change ApiService.java
public interface ApiService {
String BASE_URL = "http://www.androidbegin.com/";
#GET("tutorial/jsonparsetutorial.txt")
Call<JsonResponse> getPopulationData() ;
}
and call it like this
made an edit here
ApiService service = retrofit.create(ApiService.class);
Call<JsonResponse> call = service.getPopulationData();
call.enqueue(new Callback<JsonResponse> (){
#Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
Log.d("JSONData", response.body().toString());
ArrayList<Worldpopulation> population=new ArrayList(response.body().getWorldpopulation());
}
#Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
Log.d("JSONData", t.getMessage());
}
});
The json you are trying to parse with Retrofit contains a JSON Array as its root worldpopulation , So First you need a class WorldPopulation as follow:
public class WorldPopulation
{
private List<Flag> worldpopulation;
public List<Flag> getWorldpopulation() {
return worldpopulation;
}
public void setWorldpopulation(List<Flag> worldpopulation) {
this.worldpopulation = worldpopulation;
}
}
public interface ApiService {
String BASE_URL = "http://www.androidbegin.com/";
#GET("tutorial/jsonparsetutorial.txt")
public void getPopulationData(Callback<WorldPopulation> callback) ;
}

Retrofit get object with empty fields

I use Retrofit 2.4 and try to get data from Asp.Net Core 2.0 WebApi Service.
Here Java class:
public class Category {
private int CategoryID;
private String Name;
private String Image;
public Category(){
Name="";
Image="";
}
public Category(int categoryID, String name, String image) {
Name = name;
Image = image;
CategoryID=categoryID;
}
public int getCategoryID() {return CategoryID;}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
Here Retrofit code:
public class Common {
public static User CURRENT_USER;
public static String SERVER_NAME="http://ip_address:5000";
public static IApiService ApiService;
public Common()
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_NAME)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService = retrofit.create(IApiService.class);
}
}
public interface IApiService
{
#GET("api/Categories")
Call<List<Category>> GetCategoryColl();
}
And then i write server side via Asp.Net Core 2.0 WebApi.
I have a controller:
[Produces("application/json")]
[Route("api/Categories")]
public class CategoriesController : Controller
{
private readonly MovieAppServerContext _context;
public CategoriesController(MovieAppServerContext context)
{
_context = context;
}
// GET: api/Categories
[HttpGet]
public IEnumerable<Category> GetCategory()
{
return _context.Category;
}
// GET: api/Categories/5
[HttpGet("{id}")]
public async Task<IActionResult> GetCategory([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var category = await _context.Category.SingleOrDefaultAsync(m => m.CategoryID == id);
if (category == null)
{
return NotFound();
}
return Ok(category);
}
// PUT: api/Categories/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCategory([FromRoute] int id, [FromBody] Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != category.CategoryID)
{
return BadRequest();
}
_context.Entry(category).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CategoryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Categories
[HttpPost]
public async Task<IActionResult> PostCategory([FromBody] Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Category.Add(category);
//await _context.SaveChangesAsync();
_context.SaveChanges();
return Ok(category);
}
// DELETE: api/Categories/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCategory([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var category = await _context.Category.SingleOrDefaultAsync(m => m.CategoryID == id);
if (category == null)
{
return NotFound();
}
_context.Category.Remove(category);
// await _context.SaveChangesAsync();
_context.SaveChanges();
return Ok("Removed!");
}
private bool CategoryExists(int id)
{
return _context.Category.Any(e => e.CategoryID == id);
}
}
Here server side class of Category:
public class Category
{
[Key]
public int CategoryID { get; set; }
public String Name { get; set; }
public String Image { get; set; }
public Category()
{
}
public Category(String name, String image)
{
Name = name;
Image = image;
}
}
So, i check server code via Swagger and it works well: i get all data from Categories List.
But, when i try to get data from Android code via Retrofit - i get collection with empty objects : all fields are null or empty (i think it is default values).
So, here the code:
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
List<Category> _categoryList =new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
//some code
Common.ApiService.GetCategoryColl().enqueue(new Callback<List<Category>>() {
#Override
public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
Log.i("GetCategories",response.message());
_categoryList=response.body();
// !!!! HERE. _category list contains objects but all of them
// are empty!
}
#Override
public void onFailure(Call<List<Category>> call, Throwable t) {
Log.e("GetCategories",t.getMessage());
}
});
}
}
So, i do not know, why it happens? How to fix that?
Thank you!
You haven't added #SerializedName("json-key-name") to your fields in the Java Category class:
#SerializedName("categoryId")
private int CategoryID;
#SerializedName("name")
private String Name;
#SerializedName("image")
private String Image;
Now GSON can map JSON response to the POJO properly.
By default Gson expects the field names to be the same as the Json ones, if you want to change this behavior, you have two options:
1.Use a FieldNamingPolicy, for your case it would be UPPER_CAMEL_CASE, below a sample how to do it for Retrofit:
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_NAME)
.addConverterFactory(GsonConverterFactory.create())
.build();
2. Use the SerializedName annotation on your java fields.

Categories

Resources