What is the most common and appropriate way to update single fields of a JSON resource with a PATCH request in Retrofit?
I see 3 ways of doing it:
Using #Body to send the full object, while leaving fields that are not supposed to be updated as null, so GSON will drop them:
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #Body Post post);
Using #FormUrlEncoded and only pass the fields that are supposed to be updated, for example with a #FieldMap.
#FormUrlEncoded
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #FieldMap Map<String, String> fields);
Defining a custom model class that only contains fields that are supposed to be updated, so we don't have to set anything to null.
#PATCH("posts/{id}")
Call<Post> patchPost(#Path("id") int id, #Body PostUpdate postUpdate);
Am I missing other ways? Which one is the most commonly used?
I generally use JSON with RequestBody(Okhttp). JSON object includes just relevant fields. And then I convert it RequestBody. It's like below:
#PATCH(RestConstants.POST_EMPTY)
Call<EmptyResponseModel> postEmpty(#Body RequestBody body);
MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json.toString()));
Related
Why is price null here?
JSON is retrieved from here (you could also use multiple parameters, that is why the below object uses Maps; example). Here is CoinGeckoCoinPrice:
public class CoinGeckoCoinPrice {
#Expose
private Map<String, Map<String, Double>> price;
public double getPrice(String slug, String pair) {
...
}
}
Here is my Retrofit2 call:
#GET("/api/v3/simple/price")
Call<CoinGeckoCoinPrice> getCoinPrice(#Query("ids") String coinSlugs, #Query("vs_currencies") String pairs);
I checked logcat for any GSON error message and there is none. So why would price be null?
It works if I change Retrofit2 call to use JsonObject:
#GET("/api/v3/simple/price")
Call<JsonObject> getCoinPrice(#Query("ids") String coinSlugs, #Query("vs_currencies") String pairs);
But I want to wrap the object so I can write data retrieval functions in the CoinGeckoCoinPrice class.
The Json you are getting back doesn't have a price property on it, so Gson doesn't know that it should be parsing the bitcoin object and its price in USD to that object. Given that your returned data can be for any key (i.e. bitcoin, ethereum...) and its properties can also have any keys (i.e. usd, euros...) you'll need to manually parse this by giving Gson a custom adapter to work with.
I would like to make a POST request call with multiple params instead of one #Body param. I'm not using #FormUrlEncoded annotation on this one and I don't want to. I'm using Retrofit 2.0.
Currently, the call is made this way :
#POST("user/register")
Call<APIResponse> register(#Body RequestRegisterParams params);
with RequestRegisterParams being :
public class RequestRegisterParams {
public String username;
public String email;
public String password;
}
I would like to be able to do this (with proper annotations of course) :
#POST("user/register")
Call<APIResponse> register(String username, String email, String password);
My goal is to get rid of the data model class. Is there a way to do this or a POST request without #FormUrlEncoded must have only one #Body param ? I know it can only be one #Body param but maybe with other annotations ?
Thanks in advance !
#FormUrlEncoded
#POST("user/register")
Call<APIResponse> updateUser(#Field("username") String username, #Field("email") String email, #Field("password") String password);
#Field is Named pair for a form-encoded request.
This is the interface method:
#FormUrlEncoded
#POST (“url/myurl")
Call<JsonArray> sendParameters (#Header("x-imei") String imei, #Header("x-id-cliente") String idCliente, #Field(“param1") JsonObject param1, #Field(“param2") JsonArray param2, #Field(“param3") JsonArray param3, #Field(“param4") JsonArray param4,#Field(“param5") JsonArray param5);
And the method to use it:
Call<JsonArray> peticion= RetrofitClient.getRetrofitClient(getActivity()).sendParameters(settings.getString("imei", ""), settings.getString("idCliente", "”),param1,param2,param3,param4,param5);
This way, the call is not working.
I tried changing all the interface parameters to String, and doing param1.toString(), param2.toString() and so on in the call, and is not working neither.
Is there a simple way to send JsonObjects and JsonArrays in a POST, using Retrofit 2?
Thank you.
First you can create a custom class which you want to pass as a POST body
class CustomClass {
String param1;
String parma2;
String param3;
//all of your params with getters and setters
}
Then you change the Retrofit method according to your new CustomClass instance with the #Body annotation:
#POST (“url/myurl")
Call<JsonArray> sendParameters (#Header("x-imei") String imei, #Header("x-id-cliente") String idCliente, #Body CustomClass customClassInstance);
And eventually you make the call to post data:
CustomClass customClassInstance = new CustomClass();
customClassInstance.setParam1(...);
//...and so on
Call<JsonArray> peticion= RetrofitClient.getRetrofitClient(getActivity()).sendParameters(settings.getString("imei", ""), settings.getString("idCliente", ""), customClassInstance);
EDIT: removed the #FormUrlEncoded annotation
I want to perform request using Retrofit2 and RxJava
public static Observable<Post> getPostsAround(Location location, int offset, int limit) {
if(api==null) {
new RestService(); //initialize API in constructor
}
return api.getPostsAround(location.getLatitude(),location.getLongitude(),offset,limit)
.flatMapIterable(posts -> posts); //transform Observable<List<Post>> to Observable<Post> which emits posts onNext
}
I tried #Headers("Authorization: code) annotation, but I don't know how to change "code" in runtime.
I have found an answer:
A request Header can be updated dynamically using the #Header annotation. A corresponding parameter must be provided to the #Header. If the value is null, the header will be omitted. Otherwise, toString will be called on the value, and the result used.
#GET("user")
Call<User> getUser(#Header("Authorization") String authorization)
Hi all i call below URL using Retrofit
https://api.stackexchange.com/2.2/me?key=gQJsL7krOvbXkJ0NEI((&site=stackoverflow&order=desc&sort=reputation&access_token=HM*22z8nkaaoyjA8))&filter=default
and for that i created Interface RestInterface
//get UserId
#GET("/me&site=stackoverflow&order=desc&sort=reputation&access_token={access_token}&filter=default")
void getUserId(#Query("key") String apikey,#Path("access_token") String access_token,Callback<UserShortInfo> cb);
When i do this it always add key at the end of the URL(Output below).
I added #Query("key") as Query Parameter becoz it's dynamic.
http://api.stackexchange.com/2.2/me&site=stackoverflow&order=desc&sort=reputation&access_token=p0j3dWLIcYQCycUHPdrA%29%29&filter=default?key=gQJsL7krOvbXkJ0NEI%28%28
and that's the wrong. I got HTTP 400. Also here (( and )) converted into %28%28 and %29%29
Please help me how to make
https://api.stackexchange.com/2.2/me?key=gQJsL7krOvbXkJ0NEI((&site=stackoverflow&order=desc&sort=reputation&access_token=HM*22z8nkaaoyjA8))&filter=default
in Retrofit. I want it add #Query parameter in between URL. not at the end of the URL
Don't put query parameter inside the URL only the path parameter you can add
#GET("/me?site=stackoverflow&order=desc&sort=reputation&filter=default)
void getUserId(#Query("key") String apikey,#Query("access_token") String access_token,Callback<UserShortInfo> cb);
#Query("access_token") --> given key and value will come query URL
While sending request your URL form will like below
/me?key=?site=stackoverflow&order=desc&sort=reputation&filter=default&"your_value"&access_token="your_value"
obviously instead
#GET("/me&site=stackoverflow&order=desc&sort=reputation&access_token={access_token}&filter=default")
void getUserId(#Query("key") String apikey,#Path("access_token") String access_token,Callback<UserShortInfo> cb);
you should use
#GET("/me?site=stackoverflow&order=desc&sort=reputation&filter=default")
void getUserId(#Query("key") String apikey,#Query("access_token") String access_token,Callback<UserShortInfo> cb);
the chanege is /me& to /me? ... (and second is to use access_token as Query param too, not as a Path)
edit more explanations:
After parsing url which looks like (me&)
scheme:host/me&blablalbal=blalbla&blabla=blabla
the path is
me&blablalbal=blalbla&blabla=blabla
and there is no query paramas at all ... so adding params end with adding ?param=value at the end
but with (me?)
scheme:host/me?blablalbal=blalbla&blabla=blabla
the path is
me
and there are already some query parameters ... so addin new end with adding ¶m=value at the end :)