Retrofit parse Json with array of parameter - java

I have a problem when parsing json by using Retrofit can't get any of data , This URL request array of parameter
https://lao.busnavi.asia/api/location.php?ids%5B%5D=132&ids%5B%5D=133&ids%5B%5D=131
JSON from server that looks like this
json data
My code
LatestBusLocation.java
#SerializedName("id") private int id;
#SerializedName("status") private int status;
#SerializedName("route_id") private String routeId;
#SerializedName("lng") private double lng;
#SerializedName("lat") private double lat;
#SerializedName("accuracy") private double accuracy;
#SerializedName("speed") private double speed;
#SerializedName("heading") private float heading;
#SerializedName("date") private Date date;
Interface class
public interface ApiService {
#POST("location.php")
Call<LatestBusLocation> loadLatestBusLocation(#Query("ids[]") int[] ids);
}
MainActivity.java
int[] ids = {131, 132, 133};
Call<LatestBusLocation> call = HttpManager.getInstance()
.getService().loadLatestBusLocation(ids);
call.enqueue(new Callback<LatestBusLocation>() {
#Override
public void onResponse(Call<LatestBusLocation> call, Response<LatestBusLocation> response) {
Log.e("WorkOrNote1", "Working");
if (response.isSuccessful()) {
dao = response.body();
Log.d("daoResponse", String.valueOf(dao.getId()));
} else {
try {
Log.e("LatestBusLocation", response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<LatestBusLocation> call, Throwable t) {
Log.e("onFailure", t.toString());
}
});

Retrofit fails to map your object because you have specified an LatestBusLocation in the Call. This should be a List<LatestBusLocation>.
Aditionally, you will have to add a deserializer to map correctlly because you are getting an object (with ids keys) instead of a proper array. Look at this relationed answer

Related

how to send POST using retrofit, await process and receive response JSON?

In my app, I send a json with information to the server, which is processed and after having a result, it returns another Json response. I don't know how to read that response Json.
this is part of code:
`
private void sendData(String tipo, String dni, String instrucciones, String video) {
progressDialog.setMessage("wait ...");
progressDialog.setCancelable(false);
progressDialog.show();
ApiInterface apiInterface = SendDeviceDetails.getRetrofit().create(ApiInterface.class);
final PostModel postModel= new PostModel(tipo, dni, instrucciones, video);
Call<PostModel> call = apiInterface.PostData(postModel);
call.enqueue(new Callback<PostModel>() {
#Override
public void onResponse(Call<PostModel> call, Response<PostModel> response) {
progressDialog.dismiss();
if (response.isSuccessful()) {
Toast.makeText(MainActivity3.this, response.body().getStatus(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<PostModel> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity3.this, "error in conexion", Toast.LENGTH_SHORT).show();
}
});
`
It runs fine on submit, process, I can read the result of the service, but I don't know how to read the response json
The server sends me this json:
results JSON :{"status":"1","message":"ok","ID":"609691","NAME":"xxxxxxxxx"}
you declare model class look like this
public class PostModel {
// request
..................
........
// response
#SerializedName("status")
public String status;
#SerializedName("message")
public String message;
#SerializedName("ID")
public String ID;
#SerializedName("NAME")
public String NAME;
}
read response
PostModel postModel = response.body();
String message = postModel.message;
Toast.makeText(context, "message", Toast.LENGTH_SHORT).show();
Let's say you want to send the PostModel model as a request object and receive the PostResultModel object as a response. Then you create the interface with the method:
public interface ApiInterface {
Call<PostResultModel> postData(#Body PostModel request);
}
public class PostResultModel {
#SerializedName("status")
private String status;
#SerializedName("message")
private String message;
#SerializedName("ID")
private String id;
#SerializedName("NAME")
private String name;
// getters and setters
}
You can use this method like this:
ApiInterface apiInterface = SendDeviceDetails.getRetrofit().create(ApiInterface.class);
final PostModel postModel= new PostModel(tipo, dni, instrucciones, video);
Call<PostResultModel> call = apiInterface.postData(postModel);
call.enqueue(
new Callback<PostResultModel>() {
#Override
public void onResponse(Call<PostResultModel> call, Response<PostResultModel> response) {
if (response.isSuccessful()) {
final PostResultModel postResultModel = response.body();
// todo some logic with reponse
}
}
#Override
public void onFailure(Call<PostResultModel> call, Throwable t) {
// todo some logic when request failed
}
}
);
See this article to get more information

Method always return empty list

I am using mvp Design pattern in android development and i am using retrofit2 with it ... when i run the function to get me information from a the web it get the information but returns null list
the Response.Body come with response that mean that the code works
the model function
List<SearchDdb> searchResult;
private Context context;
public MainModel(Context context){this.context=context;}
public List<SearchDdb> searchUser(String name) {
final MainPresenter presenter = new MainPresenter(context);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Db db = retrofit.create(Db.class);
Call<List<SearchDdb>> call = db.getUsers(name);
call.enqueue(new Callback<List<SearchDdb>>() {
#Override
public void onResponse(Call<List<SearchDdb>> call, Response<List<SearchDdb>> response) {
if(!response.isSuccessful()){
presenter.showDialog();
}
searchResult = response.body();
}
#Override
public void onFailure(Call<List<SearchDdb>> call, Throwable t) {
}
});
return searchResult;
}
the SearchDdb file
private int id;
private String name;
private String grade;
private String age;
private String address;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getGrade() {
return grade;
}
public String getAge() {
return age;
}
public String getAddress() {
return address;
}
}
How i call the function
List<SearchDdb> ressult = presenter.searchUser("1");
You cant call it like List<SearchDdb> ressult = presenter.searchUser("1"); because searchUser method makes an async request via retrofit. This way searchUse returns null searchResult because response has not come yet.
Define a LiveData in your viewmodel class and observe it in your activity/fragment. When response comes from api in
onResponse in searchUser post that response to live data and use it where you observe.
If you want to see a tutorial you can look at this article.
Here is another example.

retrofit error code 404 using Multipart Post method

I want to upload two videos and some text fields into the retrofit library
using Multipart Post method, How to Send Value using the android retrofit library
API Interface
#Headers({"Accept: application/json"})
#Multipart
#POST("event")
Call<ResponsePojo> submitData(#Part MultipartBody.Part video,
#Part("device_id") String device_id,
#Part("lat") String lat,
#Part("lng") String lng,
#Part("speed") String speed,
#Part("event_type") String event_type,
#Part MultipartBody.Part videolarge);
ResponsePoja model Class
public class ResponsePojo {
#SerializedName("fileData")
#Expose
private String fileData;
#SerializedName("device_id")
#Expose
private String device_id;
#SerializedName("lat")
#Expose
private String lat;
#SerializedName("lng")
#Expose
private String lng;
#SerializedName("speed")
#Expose
private String speed;
#SerializedName("event_type")
#Expose
private String event_type;
public ResponsePojo(String fileData, String device_id, String lat, String lng, String speed, String event_type) {
this.fileData = fileData;
this.device_id = device_id;
this.lat = lat;
this.lng = lng;
this.speed = speed;
this.event_type = event_type;
}
public String getFileDatasmall() {
return fileData;
}
public void setFileDatasmall(String fileDatasmall) {
this.fileData = fileDatasmall;
}
public String getDevice_id() {
return device_id;
}
public void setDevice_id(String device_id) {
this.device_id = device_id;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public String getEvent_type() {
return event_type;
}
public void setEvent_type(String event_type) {
this.event_type = event_type;
}
Bellow Send Button Click Method ,When i click time upload all data save to server
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)
.readTimeout(100,TimeUnit.SECONDS).build();
Retrofit builder = new Retrofit.Builder()
.baseUrl(API.BaseUrl).client(client)
.addConverterFactory(GsonConverterFactory.create(new Gson())).build();
API api = builder.create(API.class);
//create file which we want to send to server.
File videoFIle = new File(String.valueOf(realUri));
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), videoFIle);
MultipartBody.Part image = MultipartBody.Part.createFormData("fileData", videoFIle.getName(), requestBody);
Call<ResponsePojo> call = api.submitData(image, "1, ", "4.667566", "54.54448", "5457", "2",image);
call.enqueue(new Callback<ResponsePojo>() {
#Override
public void onResponse(Call<ResponsePojo> call, Response<ResponsePojo> response) {
ResponsePojo body = response.body();
Toast.makeText(getApplicationContext(), String.valueOf("Code "+response.message()), Toast.LENGTH_SHORT).show();
pd.dismiss();
}
#Override
public void onFailure(Call<ResponsePojo> call, Throwable t) {
Toast.makeText(getApplicationContext(), "File "+t.toString(), Toast.LENGTH_SHORT).show();
pd.dismiss();
}
});
Postman send request method
For this instance,a 404 means there is no API for this URL.
Maybe, your URL needs to be http://192.168.0.105/register/
instead of http://192.168.0.105/register or maybe it is malformed.
Example, http://192.168.0.105//register/
This error basically related to the path(#Path) in some cases. so please check your request path just like #Path("/event").
According to the response code, the client was able to communicate with a given server, but the server could not find what was requested.
So, in this case, should check path and parameter what are we sending.
If you are using #POST and want to send data using #part you need to first convert it to RequestBody before sending it. Do the following changes
In request code
Call<ResponsePojo> submitData(#Part MultipartBody.Part video,
#Part("device_id") RequestBody device_id,...
Before calling this method you need to convert your parameter to Requestbody
RequestBody device_id = RequestBody.create(
MediaType.parse("text/plain"),
device_id);
Now use this variable as mentioned above in method call.

Nested JSON Object (Retrofit)

I'm using Retrofit to send picture request and receive this Json
{"response":{
"face":{
"value":"true",
"confidence":55
},
"gender":{
"value":"male",
"confidence":73
},
...
}}
and I'm receiving it with Retrofit....
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(END_POINT)
.build();
Mylistenerr listener = adapter.create(Mylistenerr.class);
File photo = new File(picturePath);
TypedFile image = new TypedFile("multipart/image/jpg", photo);
listener.setUserImage(
image,
new Callback<respostring>() {
#Override
public void success(respostring rp, Response arg1) {}
#Override
public void failure(RetrofitError arg0) {
pd.hide();
pd.dismiss();
Log.d("ERROR:", arg0.getLocalizedMessage());
}
});
}
private static class respostring {
private Content face;
private Content gender;
respostring() {}
}
class Content
{
private int confidence;
private String value;
Content(){}
public int getconf(){
return this.confidence;
}
public String getvalue(){
return this.value;
}
}
My interface
public interface Mylistenerr {
#Multipart
#POST("/public/test")
void setUserImage(
#Part("image") TypedFile file,
Callback<respostring> response);
}
but there is retrofit error. Is there something I miss here?
I'd recommend you using Gson for json deserialization instead since retrofit supports it very well. Then you can just create classes like this:
Your face class:
public class Face implements Serializable {
#SerializedName("value")
public boolean value;
#SerializedName("confidence")
public int confidence;
}
Your gender class:
public class Gender implements Serializable {
#SerializedName("value")
public String value;
#SerializedName("confidence")
public int confidence;
}
your response class:
public class YourResponseType implements Serializable {
#SerializedName("face")
public Face face;
#SerializedName("gender")
public Gender gender;
}
Then you can actually make retrofit doing the rest for you:
listener.setUserImage(image, new Callback<YourResonseType>() {...});
Hope that helps!

Retrofit Android Application GET JSON from Node.js Server

I solved the problem.
I was sending plain-text in the server.
Changed the line to read:
response.writeHead(200, {'Content-Type': 'application/json'});
Quick question. My friend recommended looking into Retrofit rather than using my ASync task for my REST android application. I am having one small problem since I am new to the system. The server runs using Node.js to send JSON objects by means of .stringify() and so when I retrieve an object it is a String rather than a JSON, and I cannot convert it to my List of the appropriate objects. I am guessing the error is due to a cast exception because it is sending a string because I get the exception:
com.google.gson.JsonSyntaxException
Any help would be great. Here is the code I thought would be appropriate.
Android Client Code Example below:
private void requestData() {
RestAdapter adapter = new RestAdapter.Builder().setEndpoint(ENDPOINT).build();
UnitAPI unit_api = adapter.create(UnitAPI.class);
unit_api.getUnits(new Callback<List<Unit>>() {
#Override
public void success(List<Unit> t, Response response) {
units = t;
updateDisplay();
}
#Override
public void failure(RetrofitError error) {
Log.d("Failure UnitGet()", error.getMessage());
}
});
}
Android Unit.class:
public class Unit {
private String ID;
private long bearing;
private long lat;
private long lng;
private String type;
public String getID() {
return ID;
}
public void setID(String ID){
this.ID = ID;
}
public long getBearing() {
return bearing;
}
public void setBearing(long bearing){
this.bearing = bearing;
}
public void setLat(long lat){
this.lat = lat;
}
public long getLat(){
return lat;
}
public void setLng(long lng){
this.lng = lng;
}
public long getLng(){
return lng;
}
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
}
The server sends the .json file via the command:
if (method == "GET") {
response.write(JSON.stringify(unitsJSON));
}
Any thoughts on how I can convert it to a list of units from the string on the client side or a json object on the server side?
Thanks!
I solved the problem. I was sending plain-text in the server. Changed the line to read:
response.writeHead(200, {'Content-Type': 'application/json'});
I think you must add json-parser to package using npm
then
in response write
res.end(JSON.stringfy('your resp0onse here'));

Categories