Expected BEGIN_ARRAY but was BEGIN_OBJECT in Retrofit - java

I am new to android programming and can anyone help me or point out why its giving me this error
I want to fetch some data from the server such as under the Hardware json and get the names and status, but when i call api its shows me this.

Change the line
public void onResponse(Call<List<ObjectList>> call, Response<List<ObjectList>> response) {
to
public void onResponse(Call<List<ObjectList>> call, Response<ObjectList> response) {

As per your code, you are expecting response as List. But Actual response is object. So, you need to generate model class based on your response and set in code for output.
Your Model should be like :
public class Application {
ArrayList<Object> hardware = new ArrayList<Object>();
Header HeaderObject;
ArrayList<Object> software = new ArrayList<Object>();
// Getter Methods
public Header getHeader() {
return HeaderObject;
}
// Setter Methods
public void setHeader( Header headerObject ) {
this.HeaderObject = headerObject;
}
}
public class Header {
Stamp StampObject;
private String frame_id;
private float seq;
// Getter Methods
public Stamp getStamp() {
return StampObject;
}
public String getFrame_id() {
return frame_id;
}
public float getSeq() {
return seq;
}
// Setter Methods
public void setStamp( Stamp stampObject ) {
this.StampObject = stampObject;
}
public void setFrame_id( String frame_id ) {
this.frame_id = frame_id;
}
public void setSeq( float seq ) {
this.seq = seq;
}
}
public class Stamp {
private float secs;
private float nsecs;
// Getter Methods
public float getSecs() {
return secs;
}
public float getNsecs() {
return nsecs;
}
// Setter Methods
public void setSecs( float secs ) {
this.secs = secs;
}
public void setNsecs( float nsecs ) {
this.nsecs = nsecs;
}
}
Then change below line :
public void onResponse(Call<List<ObjectList>> call, Response<Application> response) {

Change this:
#GET("system_monitor")
Call<List<ObjectList>> getHardware();
to
#GET("system_monitor")
Call<ObjectList> getHardware();

Your response return an object instead of array.
Instead of
#GET("system_monitor")
Call<List<ObjectList>> getHardware();
use
#GET("system_monitor")
Call<ObjectList> getHardware();
And then use it like below:
Call<ObjectList> call = webRequestAPI.getHardware();
call.enqueue(new Callback<ObjectList>() {
#Override
public void onResponse(Call<ObjectList> call, Response<ObjectList> response) {
if (!response.isSuccessful()) {
textViewHardwareName.setText("Code: " + response.code());
return;
}
ObjectList system_monitor = response.body();
...
}
#Override
public void onFailure(Call<ObjectList> call, Throwable t) {
textViewHardwareName.setText(t.getMessage());
}
});

The best thing for your scenario hardware and Software are as objects , which have two property
1.Name 2. Object status.
So I recommend you to create a class name as System and put there these two variables so finally your class looks like :
Class System
{
String object_name;
boolean object_status;
}
and your getter setter .
And update your model class like this
#SerializedName("hardware")
#Expose
public List<System> hardware;
#SerializedName("software")
#Expose
public List<System> software;
and change your retrofit response holder as.
public void onResponse(Call<List<ObjectList>> call, Response<ObjectList>
response) {

Related

How to create a polymorphic structure that can work for both success and error responses in Java?

I'm working on a class that will get a list of strings and process them asynchronously using CompletableFutures. Each string is processed by invoking another class that will perform several operations and return a response or throw an exception if there is an error.
I would like to aggregate the responses that I get, whether they have a valid response or an exception and return them as a list to the caller. I would like the caller to be able to expect a list of SomeResponse and be able to interpret them using polymorphism.
However, I'm stuck on determining if this can be done using polymorphism at all, given that the fields for the success and error response are completely different. I have added some pseudo code below on one alternative I have thought of. Basically have SomeResponse be an interface with an isSuccess method. This will allow the caller to know if it's an error or not. However, the caller would still have to cast it to the correct implementation in order to get the value or the error. Is there a better way to approach this? My requirement is being able to return both a success and error response for each given request in the list. If there is an exception, we don't want to abort the entire operation.
public MyProcessorClass {
private final SomeOtherClass someOtherClass;
public List<SomeResponse> process(List<String> requestList) {
return requestList.stream().map(this::procesRequest)
.collectors(Collect.tolist()):
}
private processRequest(String request) {
CompletableFuture completableFuture = CompletableFuture
.supplyAsync(() => {
return new SomeSuccessResponse(someOtherClass.execute(request));
})
.exceptionally(e -> {
return new SomeErrorResponse(e.getCause);
});
return completableFuture.get();
}
}
public interface SomeResponse {
boolean isSuccess();
}
public class SomeSuccessResponse implements SomeResponse {
private final String value;
#Getter
private final boolean success;
public SomeSuccessResponse(String value) {
this.value = value;
this.success = true;
}
}
public class SomeErrorResponse implements SomeResponse {
private final Throwable error;
#Getter
private final boolean success;
public SomeErrorResponse(Throwable error) {
this.error = error;
this.success = false;
}
}
What you want is the visitor pattern https://en.wikipedia.org/wiki/Visitor_pattern
public class Main {
interface IResponse {
void acceptHandler(IResponseHandler handler);
}
static class ResponseA implements IResponse {
#Override
public void acceptHandler(IResponseHandler handler) {
handler.handle(this);
}
}
static class ResponseB implements IResponse {
#Override
public void acceptHandler(IResponseHandler handler) {
handler.handle(this);
}
}
public interface IResponseHandler {
void handle(ResponseA response);
void handle(ResponseB responseB);
}
public static void main(String[] args) {
final IResponseHandler handler = new IResponseHandler() {
#Override
public void handle(ResponseA response) {
System.out.println("Handle ResponseA");
}
#Override
public void handle(ResponseB responseB) {
System.out.println("Handle ResponseB");
}
};
final IResponse someResponse = new ResponseA();
someResponse.acceptHandler(handler);
}
}

why do we use a call list with retrofit

I have an example ,I want to understand some parts,In this exampl ,It was working fine ,but when I changed part
from:
call list<model>> method();
to:
call <model> method();
It caused an error ,What's the reason for that?
What is the difference between the two cases?
// MainActivity :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GetData service = RetrofitClient.getRetrofitInstance().create(GetData.class);
Call<RetroUsers> call = service.getAllUsers();
call.enqueue(new Callback<RetroUsers>() {
#Override
public void onResponse(Call<RetroUsers> call, Response<RetroUsers> response) {
Log.i("print", "" + response.body().getUser());
}
#Override
public void onFailure(Call<RetroUsers> call, Throwable t) {
Log.i("print", "Dont" + t.getMessage());
}
});
}
///Error message :
I/print: Dontjava.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
// interface GetData:
public interface GetData {
#GET("/users")
Call<RetroUsers>getAllUsers();
/*
#GET("/users")
Call<List<RetroUsers>> getAllUsers();
*/
}
// RetrofitClient :
public class RetrofitClient {
private static Retrofit retrofit;
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
// model class :
public class RetroUsers {
#SerializedName("name")
private String name;
public RetroUsers(String name) {
this.name = name;
}
public String getUser() {
return name;
}
public void setUser(String name) {
this.name = name;
}
}
This: Call<RetroUsers> getAllUsers();
will cause you an error because the getAllUsers() will return more than one records of RetroUsers. Due to which it requires you to provide it a type as List so that its datatype is set to List and it can then handle multiple records.
Go through basics of Core Java to better understand this.
In one case you tell the deserializer that you expect a single Model, in the other case you tell it to expect a list of models, aka a List<Model>. Depending on what data you actually get you need to use one or the oter.
Of course you can "hide" the List<...> within your model by not using List<Model> but:
public class MoreThanOneModel {
public List<Model> entries;
...
}
But that does not change the underlying reasoning.

Retrofit different call and response json bodies

How can be done retrofit PUT with different types of call and responce bodies?
I have a limitation with error. Types must be identical <T> and <T>.
Responce bodie can contain int value, but call should not, because when i initialize CallBody object with int value, it already contain n1=0, and send this parameter to server.
#PUT("/api/test")
Call<CallBody> test1(#Body CallBody params_body);
public class CallBody {
public String id;
}
public class ResponceBody {
public String s1;
public int n1;
}
public void Test(String id) {
CallBody params_body = new CallBody();
params_body.id = id;
Call<CallBody> call1 = apiInterface.test1(params_body);
call1.enqueue(new Callback<CallBody>() {
#Override
public void onResponse(Call<CallBody> call, Response<ResponceBody> response) {
ResponceBody response = response.body();
}
#Override
public void onFailure(Call<CallBody> call, Throwable t) {
call.cancel();
}
});
}
Try,
public class ResponceBody {
public String s1;
public Integer n1;
}

Building a library that uses Retrofit internally, wrapping responses

I'm trying to build a library that basically wraps our api. Basically, the structure im going for is something like this:
MySDK mySDK = new MySDK("username", "password");
mySDK.getPlaylistInfo("3423", 2323, new CustomCallback<>(){
//on response
//on failure
});
So with vanilla Retrofit, an api call usually looks something like the following:
ApiService api = retrofit.create(ApiService.class);
Call<Response> call = api.getPlaylistInfo()
call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
//handle response
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
//handle failure
}
});
Basically, how would I wrap retrofits callback system into my own? Note, the reason for needing to do this is to preprocess the data returned from the api before delivering the final response.
I've written something similar so it might help you getting started, this follows an implementation I'v written for Volley, and re-used when I migrated to Retrofit2 so it resembles it (this SO question).
Create a global object (what you would refer to as MySDK) as a singelton class that handles your requests:
create a singleton class, which you instatiate when you're application comes up:
public class NetworkManager
{
private static final String TAG = "NetworkManager";
private static NetworkManager instance = null;
private static final String prefixURL = "http://some/url/prefix/";
//for Retrofit API
private Retrofit retrofit;
private ServicesApi serviceCaller;
private NetworkManager(Context context)
{
retrofit = new Retrofit.Builder().baseUrl(prefixURL).build();
serviceCaller = retrofit.create(ServicesApi.class);
//other stuf if you need
}
public static synchronized NetworkManager getInstance(Context context)
{
if (null == instance)
instance = new NetworkManager(context);
return instance;
}
//this is so you don't need to pass context each time
public static synchronized NetworkManager getInstance()
{
if (null == instance)
{
throw new IllegalStateException(NetworkManager.class.getSimpleName() +
" is not initialized, call getInstance(...) first");
}
return instance;
}
public void somePostRequestReturningString(Object param1, final SomeCustomListener<String> listener)
{
String url = prefixURL + "this/request/suffix";
Map<String, Object> jsonParams = new HashMap<>();
jsonParams.put("param1", param1);
Call<ResponseBody> response;
RequestBody body;
body = RequestBody.create(okhttp3.MediaType.parse(JSON_UTF), (new JSONObject(jsonParams)).toString());
response = serviceCaller.thePostMethodYouWant("someUrlSufix", body);
response.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
{
try
{
String response = rawResponse.body().string();
// do what you want with it and based on that...
//return it to who called this method
listener.getResult("someResultString");
}
catch (Exception e)
{
e.printStackTrace();
listener.getResult("Error1...");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable throwable)
{
try
{
// do something else in case of an error
listener.getResult("Error2...");
}
catch (Exception e)
{
throwable.printStackTrace();
listener.getResult("Error3...");
}
}
});
}
public void someGetRequestReturningString(Object param1, final SomeCustomListener<String> listener)
{
// you need it all to be strings, lets say id is an int and name is a string
Call<ResponseBody> response = serviceCaller.theGetMethodYouWant
(String.valueOf(param1.getUserId()), param1.getUserName());
response.enqueue(new Callback<ResponseBody>()
{
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
{
try
{
String response = rawResponse.body().string();
// do what you want with it and based on that...
//return it to who called this method
listener.getResult("someResultString");
}
catch (Exception e)
{
e.printStackTrace();
listener.getResult("Error1...");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable throwable)
{
try
{
// do something else in case of an error
listener.getResult("Error2...");
}
catch (Exception e)
{
throwable.printStackTrace();
listener.getResult("Error3...");
}
}
});
}
}
This works with your interface (example with POST and GET request, GET could be without params):
public interface BelongServicesApi
{
#POST("rest/of/suffix/{lastpart}") // with dynamic suffix example
Call<ResponseBody> thePostMethodYouWant(#Path("lastpart") String suffix, #Body RequestBody params);
#GET("rest/of/suffix") // with a fixed suffix example
Call<ResponseBody> theGetMethodYouWant(#Query("userid") String userid, #Query("username") String username);
}
when your application comes up:
public class MyApplication extends Application
{
//...
#Override
public void onCreate()
{
super.onCreate();
NetworkManager.getInstance(this);
}
//...
}
a simple listener interface for your callback (seperate file would do good):
public interface SomeCustomListener<T>
{
public void getResult(T object);
}
and finally, from wherever you want, the context is already in there, just call:
public class BlaBla
{
//.....
public void someMethod()
{
//use the POST or GET
NetworkManager.getInstance().somePostRequestReturningString(someObject, new SomeCustomListener<String>()
{
#Override
public void getResult(String result)
{
if (!result.isEmpty())
{
//do what you need with the result...
}
}
});
}
}
you can use any object with the listener, just parse the response string to a corresponding object, depending on what you need to receive and you can call that from everywhere (onClicks, etc.), just remember the objects need to match between methods.
Hope this Helps!

Generics overloading of method - workaround

this question was asked many times but I couldn't find elegant workaround for it.
This example works as desired:
public class RequestWrapper<T> {
private final T request;
private final Class<T> type;
public RequestWrapper(T request, Class<T> type) {
this.request = request;
this.type = type;
}
public T getRequest() {
return request;
}
public Class<T> getType() {
return type;
}
}
public class Service {
private void invoke(String request) {
System.out.println("String:" + request);
}
private void invoke(Object request) {
System.out.println("Object:" + request + "," + request.getClass().getSimpleName());
}
public static void main(String[] args) {
RequestWrapper<String> sw = new RequestWrapper<String>("A", String.class);
RequestWrapper<Integer> iw = new RequestWrapper<Integer>(Integer.valueOf(0), Integer.class);
new Service().invoke(sw.getRequest());
new Service().invoke(iw.getRequest());
}
}
But I would need to add one more method to Service class which do something before/after call of invoke method:
public void invoke(RequestWrapper<?> wrapper) {
try {
// ...
invoke(wrapper.getType().cast(wrapper.getRequest()));
invoke(wrapper.getRequest());
} catch(Exception e ) {
// ...
}
}
then the main method would contain:
new Service().invoke(sw);
I understand the reason why the invoke(Object request) is used instead of invoke(String request).
What would be an elegant solution to call proper invoke method and be able to do some common actions before/after it?
To have an interface e.g. Invoker, implement it e.g. StringInvoker, Invoker> and call map.get(wrapper.getType()).invoke(wrapper.getRequest()) is possible solution but I expect something better.
You can check the type and explicitly cast it, for example (I also added Integer so you can see branching on more types):
Class<?> c = wrapper.getType();
if (c == String.class)
invoke((String) wrapper.getRequest()); // Invokes invoke(String)
else if (c == Integer.class)
invoke((Integer) wrapper.getRequest()); // Invokes invoke(Integer)
else
invoke(wrapper.getRequest()); // Invokes invoke(Object)
Note:
If you go on this path, you don't even need to store the request type in the RequestWrapper class because you can just as easily use the instanceof operator on the request itself to check its type. And if you "get rid" of the request type, your current RequestWrapper class will only contain the request so the RequestWrapper is not even needed in this case.
Visitor patter can serves to solve it. Only drawback is that there isn't possible to write:
new Service().invoke(new RequestWrapper<String>("A"));
My implementation:
public class Service {
public void invoke(RequestWrapper<?> wrapper) {
try {
// ...
wrapper.invoke(this);
} catch(Exception e ) {
// ...
}
}
public void invoke(String request) {
System.out.println("String:" + request);
}
public void invoke(Boolean request) {
System.out.println("Boolean:" + request);
}
public static void main(String[] args) {
RequestWrapper<Boolean> rw = new BooleanRequestWrapper(Boolean.TRUE);
new Service().invoke(rw);
}
}
abstract class RequestWrapper<T> {
protected final T request;
public RequestWrapper(T request) {
this.request = request;
}
public abstract void invoke(Service v);
}
class BooleanRequestWrapper extends RequestWrapper<Boolean> {
public BooleanRequestWrapper(Boolean request) {
super(request);
}
public void invoke(Service service) {
service.invoke(request);
}
}

Categories