I have an instance where I need to pass multiple of the same named parameters to a server (array of data).
Changing it is not a possibility.
http://test.com?test[]=1&test[]=2&test[]=3
How do I accomplish this with RetroFit? I see that you can pass a map of values, but that doesn't help as the keys are all identical.
Any help would be great... really hoping there's a clean way/workaround or else I'm going to need to use another api lib and do a project refactor.
Retrofit as of 1.4.0 added the ability to send an array or List as a #Field or #Query parameter.
New: #Query and #EncodedQuery now accept List or arrays for multiple values.
New: #Field now accepts List or arrays for multiple values.
I am using retrofit:1.9.0, one way of doing http://test.com?test[]=1&test[]=2&test[]=3 is like this
void test(#Query("test[]") ArrayList<String> values);
Related
i want to get a data on Internet use Retrofit Library
my code look like this :
#GET("?key={key}&q={quotes}")
Call<List<Pixabay.hits>> getTheData(#Query("key") String key, #Query("quotes") String quotes);
java.lang.IllegalArgumentException: URL query string key={key}&q={quotes} must not have replace block. For dynamic query parameters use #Query.
for method api.getTheData
I get that problem, how to solve this? thank you.
you don't have to write query parameters in your path.
#Query will do that for you.
replace
#GET("?key={key}&q={quotes}")
with
#GET("/")
Precisely, {something} parameter can be used only in path variable.
For example,
#GET("/key/{key}")
In this case, you can use #Path annotation instead of #Query.
If you specify #GET("key?a=5"), then any #Query("b") must be appended using &, producing something like key?a=5&b=7.
If you specify #GET("key"), then the first #Query must be appended using ?, producing something like key?b=7.
So in your case no need to implement here like ?key={key}&q={quotes} just add
your domain #GET("your_domain/")
I am new to GSON, JSON & hence asking the question:
At the android end, I have to send a booking information to the REST WS on the server. So here is the question:
I have a BookingDTO & I use GSON to serialize it. I send it the REST WS on the server. Now do I also need the same BookingDTO at the server end for GSON deserialize it? (But that would mean tight coupling right?) Do I have to use GSON or can I use normal JSON?
What should be my approach?
You can use Json and parse that content into your objects or directly deal with JsonObject and JsonArray in your methods (server side).
if you want to use objects like BookingDTO you can either re create the classes on android project or reuse those classes from your server side, (or vice versa).
by creating a JAR file that only contains those classes (ex, export model package only) where all POJO classes are located.
using a JAR file makes you maintain a consistency between server and client code, when you add/delete a field, you don't have to change 2 classes, just change in one place and re export the JAR.
now to the tight coupling issue, i don't think there is a one here.
because you are using a list of classes (and you need them in 2 or more separate locations/projects...) this is not coupling, this is reusing same code which should be a good practice.
Coupling is -for example- when Class A is a member of Class B, but it's not when you use Class A and Class B in 2 different systems/components ...
do I also need the same BookingDTO at the server end for GSON
deserialize it?
Simply put, yes, you'll have to prepare a POJO in order to receive the request. So, for that to happen, JSON deserializer will try to parse the properties off JSON request and map that to a POJO of server.
With Spring, we do stuffs like the following. This is a creating a controller of POST request type expecting to habe a param of BookingDTO type. We use Jackson library for JSON serialize and deserialize.
#RequestMapping(value = {"/update"}, method = RequestMethod.POST)
#ResponseBody
public void update(#RequestBody BookingDTO bookingDTO) throws FamsException {
// Do what you intend to do with this bookingDTO object sent from client side(Android)
}
As it stands, if your JSON property name matches with the property name and type of BookingDTO then it can map those and you'll get BookingDTO bookingDTO object with all the matched properties.
Be sure not to send JSON request with property that isn't in the BookingDTO POJO. Otherwise, server will throw a 400 BAD REQUEST error.
Note that, you can also send Map as parameter. This won't require a matching POJO at server side. You can construct a different object by getting the data out of Map the way you like.
Hope you get the idea.
I'm a bit confused, as from a long time i am saving the json response directly to an ArrayList> and displaying to my listView, but now, looking on other people code i noticed that they are using POJO class to interact with JSON, Is it is better way? if it is please explain why? cause using POJO means I have to write extra code, But if saving the response directly to the arraylist make my work done, then why should i use a POJO class?
So, Pojo usage better due to OOP pattern, because you work at runtime with your Java object without intermediate Json parse. Manual json parsing too ugly due to code style(its my opinion).
But if saving the response directly to the arraylist make my work done
If, you collect your object in Maps, you can apply different features out of the box(sort, compare etc) to your map, but in case when your map contains POJO instead of JSONS.
Encapsulation. When you work with dates for examples or with type, its pretty good to use getters/setters for data mapping instead of manual parsing again and again.
4.Object scaling and mapping:
Lets image that we have some object user:
public class User{
int id;
#SerializedName("specific_id_for_blah_blah")
private int mSpecId
#SerializedName("date_of_birthaday")
private String mBDay;
public Date getBirthday() {
return new Date(mBDay);
}
}
What I want to say by this example.
You can map your json to POJO with one line of code only
User user = new Gson.fromJson(response, User.class);
Pretty simple isn't?.
Name serialization. When your response contain key name which looks to long or weird, you can use your own style naming with easy changes, just with small annotation. mSpecId returns value of "specific_id_for_blah_blah"
Platform specific encapsulation. You can use only platform specific object at your runtime, instead parsing operations in your business logic. String with data -> Date or Calendar
Also you can override Object methods in your POJO (equals, hashcode, toString) for your logic spec. operations.
If your serverside change some key you can change name of key in POJO instead looking through where you parse it before. IN same case you can add new field and setter/getter, if some of parameter will be added to your response
There is no right and wrong answer here. It all depends on your use case. If your solution works, and you are happy with it, I don't see why do you need to change it.
If I had to choose, I would go with a POJO class to represent the response, but this is a subjective opinion. I think that you have the following benefits:
It's cleaner - having a separate, dedicated class to represent your payload gives you the ability to be more specific in your code. You are no longer manipulating Maps of key - value pairs, but instances of a specific class, that can have a more specific behaviour. You can specify natural ordering, criteria for equality, etc - things that may be useful for your program's logic
It's simpler - I would prefer calling a getter every time then accessing a map by a property name and getting an Object back. The logic of the program will be much simpler and safer.
It's better in terms of OOP best practices - the whole point behind OOP is to have objects, that define properties and behaviours. IMHO, using POJOs to represent responses forces you to adhere more closely to best practices.
There are also some cases that will fit the no - POJO approach better - for example, if you only display your data, not manipulating it in any way inside the app. Or if you want to shave off some time for the complex parsing that may be needed if you are trying to inflate object hierarchies.
My best suggestion is - profile your app, check your use cases and make an educated decision which approach is better.
I wanted to use retrofit library for parsing and posting the data by passing some parameters. But When defining model class some times we will use #Serialized in-front of variable, What is the use of that Serialized.And What is the difference between #Get and #Query in passing params to API.Can Any one explain the difference.
Lets say you have api method #GET("/api/item/{id}/subitem/") so by using #Path("id") you can specify id for item in path. However your api may take additional parameters in query like sort, lastupdatetime, limit etc so you add those at end of url by #Query(value = "sort") String sortQuery
So full method will look like:
#GET("/api/item/{id}/subitem")
SubItem getSubItem(#Path("id") int itemId, #Query("sort") String sortQuery, #Query("limit") int itemsLimit);
and calling api.getSubItem(5, "name", 10) will produce url #GET("/api/item/5/subitem/?sort=name&limit=10")
and #Get is HTTP method
http://www.w3schools.com/tags/ref_httpmethods.asp says
Two commonly used methods for a request-response between a client and
server are: GET and POST.
GET - Requests data from a specified resource POST - Submits data to
be processed to a specified resource
#GET is request method. You mark method with that.
#Query is query parameter (i.e. the one in the URL). You mark method parameters with that.
#Serialized probably does not belong to Retrofit, look at its package name (move cursor there and press `Ctrl+Q in Android studio)
I'd like to send a POST request with a content like the following:
api=1&os=android&appVersion=12345
Is it possible to have a POJO with just that variables and pass that to
#FormUrlEncoded
#POST("/sendData")
void sendData(#FieldMap MyPojo myPojo, Callback<MyResponse> callback);
With FieldMap it doesn't work, is there another way?
Unfortunately this won't work out of the box. You have two options:
If you only have a handful of Pojos, you can define a MyPojo.toFieldMap() method to build a field map of form values and pass it to your sendData() method.
If you have a large number of Pojos, you can write a custom FormEncodedConverter by implementing the Converter interface in your project. I reckon this will need a combination of annotations and reflection to discover the public members of your MyPojo class. Examples of custom converters are available here.