I have a POJO that contains a single authentication token in a string variable. I need to send this to my API using the following template:
{ “auth” : { api_key”:”XXXX” } }
I am using moshi to convert my POJOs to JSON, which returns
{"api-key":"XXXX"}
How can I add the extra brackets on the outside of my current one using a retrofit converter?
You can use Moshi-Lazy-Adapters to wrap the json. Just use the following annotation when you send the body:
#POST("your_post_url")
Call<YourResponseTypeHere> sendApiKey(#Body #Wrapped({"auth", "api_key"}) String apiKey);
The library's adapter will do the rest. And you don't need to declare an extra object.
I think you should use oAuth authentication. Then, you can use an interceptor for Retrofit and populate that token.
Related
I have an API which its response is kind of dynamic. I mean sometimes it return a Jason object with "token" value, and sometimes it returns with "message" value. For handling this scenario I decided to have both field in my data class like below:
data class response {
val message:String;
val token:String;
}
Now I want to make both fields optional in Kotlin serialization. I mean, I want to tell Kotlin serialization that if you couldn't find token in response JSON it's ok to ignore it.
How can I achieve this?
All Kotlin properties with default values are automatically optional.
All I need to do is this:
data class response {
val message:String="";
val token:String="";
}
I am trying to parse the results of an API call which returns a unique first property.
{
"AlwaysDifferent12345": {
"fixedname1" : "ABC1",
"fixedname2" : "ABC2"
}
}
I am using retrofit2 and jackson/gson and cannot figure out how to cope with dynamic property names within the retrofit2 framework. The following works fine
data class AlwaysDifferentDTO(
#JsonProperty("AlwaysDifferent12345") val alwaysDifferentEntry: AlwaysDifferentEntry
)
I have tried
data class AlwaysDifferentDTO(
#JsonProperty
val response: Map<String, AlwaysDifferentEntry>
)
But this returns errors Can not instantiate value of type... The return value from the API is fixed i.e. map<string, object>.
I have read you can write a deserializer but it looks like I need to deserialize the whole object when all I want to do is just ignore the string associated with the response.
I have read
https://discuss.kotlinlang.org/t/set-dynamic-serializedname-annotation-for-gson-data-class/14758
and several other answers. Given unique properties names are quite common it would be nice to understand how people deal with this when using retrofit2
Thanks
Because the JSON doesn't have a 1-to-1 mapping Jackson can't map it automatically using annotations. You are going to need to make your own Deserializer.
In this tutorial you can learn how to create your own custom Deserializer for Jackson. https://www.baeldung.com/jackson-deserialization
In the tutorial you will see the first line under the deserialize function is
JsonNode node = jp.getCodec().readTree(jp);
using this line you can get the JSON node as a whole and once you have it you can call this function
JsonNode AlwaysDifferent12345Node = node.findParent("fixedname1");
Now that you have that node you can retrieve its value like shown in the rest of the tutorial. Once you have all the values you can return a new instance of the AlwaysDifferentDTO data class.
I have a problem with handling responses in YAML format in Retrofit. Until now I only handled the response body in JSON format or plain text. For these types, I always have prepared converters like gson, jackson for JSON and scalars for plain text. I found repository with all converters: retrofit-convertes.
In the documentation is a short mention that I need to create my own converter for this type.
If you need to communicate with an API that uses a content-format that Retrofit does not support out of the box (e.g. YAML, txt, custom format) or you wish to use a different library to implement an existing format, you can easily create your own converter. Create a class that extends the Converter.Factory class and pass in an instance when building your adapter.
Sadly, I don't see any tutorial on how to create such a converter. Is there any documentation explaining how to do this or is there any other option to handle such a case?
In your case you can use Jackon with yaml data formats.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("<your base url>")
.addConverterFactory(JacksonConverterFactory.create(new ObjectMapper(new YAMLFactory())))
.build();
For more informating check the following links:
https://github.com/square/retrofit/tree/master/retrofit-converters/jackson
https://github.com/FasterXML/jackson-dataformats-text/tree/master/yaml
I am facing a problem when trying to send an Http post request to the backend of my application. I am trying to send a post request like this :
{"a":[{"data":"https://news.google.com/rss/search?q=Pallini&hl=el"}]}
and instead it is being send something like this:
{"a":[{"data\":\"https://news.google.com/rss/search?q=Pallini&hl=el"}]}
or:
{"a":[{\"data\":\"https://news.google.com/rss/search?q=Pallini&hl=el\"}]}
So, I have a list that contains strings and every time I add the string that I want it to be shown in the json array, the code is like this:
var arrayListForA: ArrayList<JsonElement>? = arrayListOf()
config.forEach {
arrayListForA?.add(it)
}
The config is an another list that contains the jsons object as strings.
My question is, if there is any way to create the http post request body in Kotlin with the use of classes, objects etc, in a more automated way ?! for example, instead of a list with strings, I could use a list with Data class objects.
val dataList : ArrayList<Data> = arrayListOf()
where Data class is :
#Parcelize
data class Data(
#Expose #SerializedName("data") val data: String?
) : Parcelable
Is there any solution/idea to send the body of the post request as I need it ?
You can use retrofit and okhttp for this in Android. Retrofit helps you deal with networking easily. Also you will be able to post a custom data model as body in the api request. The interface will look something like given below. You can read more about retrofit here. retrofit
#POST(Urls.PURCHASE)
fun purchase(#Body purchaseAddonReqModel: PurchaseReqModel):Single<BaseResponse<EmptyResponse>>
Here you can add your custom model by adding the #Body annotation
I am using retrofit an get Bad Request , I would want to know if there is a place in this library where builds the full JSON in string format before sending it.
If it's about inspecting the JSON at runtime for debugging purposes, you can call setLogLevel(LogLevel.FULL) on your RestAdapter.Builder.
FULL logs the headers, body and metadata for both requests and responses to logcat.
new String(((TypedByteArray) request.getBody()).getBytes());
In order to build a JSON formatted body, create an object with a class whose properties are the same that you want to send to the server. The GSON Library set up (or whichever library you are using) with the RestAdapter should send the request with the body in JSON format.
Also ensure that the call is #POST annotated and the parameter annotd with #Body Below is an example:
#POST("/login")
User login(#Body LoginUser loginUser);