Retrofit - add field dynamically during serialization
up vote
0
down vote
favorite
I'm currently using Retrofit 2.3 in my Android project and recently the API we are using was updated so that it needs to have "version":number
in JSON body in all POST requests. So let's say we need to pass UserCredentials object - previously body of the request was simply serialized using GSON converter and looked like this
{"username":"myUsername", "password":"myPassword"}
and now it has to have additional "version" field:
{"username":"myUsername", "password":"myPassword", "version":1}
I've googled couple of hours how to set custom converter factory to retrofit but all I found was how to exclude certain fields from serialization. I know I could simply add "version"
field to all my POJOs but I found this approach 'dirty' as it's going to be used only during sending data to server.
Has anyone did something like this previously?
android gson retrofit
add a comment |
up vote
0
down vote
favorite
I'm currently using Retrofit 2.3 in my Android project and recently the API we are using was updated so that it needs to have "version":number
in JSON body in all POST requests. So let's say we need to pass UserCredentials object - previously body of the request was simply serialized using GSON converter and looked like this
{"username":"myUsername", "password":"myPassword"}
and now it has to have additional "version" field:
{"username":"myUsername", "password":"myPassword", "version":1}
I've googled couple of hours how to set custom converter factory to retrofit but all I found was how to exclude certain fields from serialization. I know I could simply add "version"
field to all my POJOs but I found this approach 'dirty' as it's going to be used only during sending data to server.
Has anyone did something like this previously?
android gson retrofit
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm currently using Retrofit 2.3 in my Android project and recently the API we are using was updated so that it needs to have "version":number
in JSON body in all POST requests. So let's say we need to pass UserCredentials object - previously body of the request was simply serialized using GSON converter and looked like this
{"username":"myUsername", "password":"myPassword"}
and now it has to have additional "version" field:
{"username":"myUsername", "password":"myPassword", "version":1}
I've googled couple of hours how to set custom converter factory to retrofit but all I found was how to exclude certain fields from serialization. I know I could simply add "version"
field to all my POJOs but I found this approach 'dirty' as it's going to be used only during sending data to server.
Has anyone did something like this previously?
android gson retrofit
I'm currently using Retrofit 2.3 in my Android project and recently the API we are using was updated so that it needs to have "version":number
in JSON body in all POST requests. So let's say we need to pass UserCredentials object - previously body of the request was simply serialized using GSON converter and looked like this
{"username":"myUsername", "password":"myPassword"}
and now it has to have additional "version" field:
{"username":"myUsername", "password":"myPassword", "version":1}
I've googled couple of hours how to set custom converter factory to retrofit but all I found was how to exclude certain fields from serialization. I know I could simply add "version"
field to all my POJOs but I found this approach 'dirty' as it's going to be used only during sending data to server.
Has anyone did something like this previously?
android gson retrofit
android gson retrofit
asked Nov 7 at 17:28
Alexandr Zhurkov
757
757
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17
add a comment |
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
I did it but not exactly the way you want, you can create BaseRequest POJO class in which you can use version number and extend that class to other POJO classes you are using like this :
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
Extend this base POJO class is to other POJO classes to use the version number like this :
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
There are lots of benefits of this approach like if you need one more field in your APIs then you don't need to change all of the apis. You can achieve that just by adding a field in your baserequest.
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
add a comment |
up vote
0
down vote
Resolved this issue with custom interceptors for OkHTTP client. So I've created custom interceptor that would analyze outgoing request and alter its body JSON data if it meets certain criteria.
okHttpClientBuilder.addInterceptor(CustomInterceptor(1))
Works like a charm!
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
class CustomInterceptor (private val version: Int): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestBody = request.body()
val subtype = requestBody?.contentType()?.subtype()
if(subtype != null
&& subtype.contains("json")) {
val bodyWithToken = addVersionParamToJSONBody(requestBody)
if(null != bodyWithToken){
val requestBuilder = request.newBuilder()
request = requestBuilder
.post(bodyWithToken)
.build()
}
}
return chain.proceed(request)
}
private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
val customRequest = bodyToString(requestBody)
return try{
val jsonObject = JSONObject(customRequest)
jsonObject.put("version", version)
RequestBody.create(requestBody?.contentType(), jsonObject.toString())
} catch (e: JSONException){
e.printStackTrace()
null
}
}
private fun bodyToString(requestBody: RequestBody?): String{
return try {
val buffer = Buffer()
requestBody?.writeTo(buffer)
buffer.readUtf8()
} catch (e: IOException){
e.printStackTrace()
""
}
}
}
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
I did it but not exactly the way you want, you can create BaseRequest POJO class in which you can use version number and extend that class to other POJO classes you are using like this :
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
Extend this base POJO class is to other POJO classes to use the version number like this :
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
There are lots of benefits of this approach like if you need one more field in your APIs then you don't need to change all of the apis. You can achieve that just by adding a field in your baserequest.
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
add a comment |
up vote
1
down vote
I did it but not exactly the way you want, you can create BaseRequest POJO class in which you can use version number and extend that class to other POJO classes you are using like this :
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
Extend this base POJO class is to other POJO classes to use the version number like this :
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
There are lots of benefits of this approach like if you need one more field in your APIs then you don't need to change all of the apis. You can achieve that just by adding a field in your baserequest.
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
add a comment |
up vote
1
down vote
up vote
1
down vote
I did it but not exactly the way you want, you can create BaseRequest POJO class in which you can use version number and extend that class to other POJO classes you are using like this :
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
Extend this base POJO class is to other POJO classes to use the version number like this :
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
There are lots of benefits of this approach like if you need one more field in your APIs then you don't need to change all of the apis. You can achieve that just by adding a field in your baserequest.
I did it but not exactly the way you want, you can create BaseRequest POJO class in which you can use version number and extend that class to other POJO classes you are using like this :
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
Extend this base POJO class is to other POJO classes to use the version number like this :
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
There are lots of benefits of this approach like if you need one more field in your APIs then you don't need to change all of the apis. You can achieve that just by adding a field in your baserequest.
answered Nov 7 at 18:05
Ajay Chauhan
152114
152114
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
add a comment |
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
I wouldn't want to do that due to several factors: "version" is used only during API calls and that I would prefer composition over inheritance
– Alexandr Zhurkov
Nov 7 at 19:19
add a comment |
up vote
0
down vote
Resolved this issue with custom interceptors for OkHTTP client. So I've created custom interceptor that would analyze outgoing request and alter its body JSON data if it meets certain criteria.
okHttpClientBuilder.addInterceptor(CustomInterceptor(1))
Works like a charm!
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
class CustomInterceptor (private val version: Int): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestBody = request.body()
val subtype = requestBody?.contentType()?.subtype()
if(subtype != null
&& subtype.contains("json")) {
val bodyWithToken = addVersionParamToJSONBody(requestBody)
if(null != bodyWithToken){
val requestBuilder = request.newBuilder()
request = requestBuilder
.post(bodyWithToken)
.build()
}
}
return chain.proceed(request)
}
private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
val customRequest = bodyToString(requestBody)
return try{
val jsonObject = JSONObject(customRequest)
jsonObject.put("version", version)
RequestBody.create(requestBody?.contentType(), jsonObject.toString())
} catch (e: JSONException){
e.printStackTrace()
null
}
}
private fun bodyToString(requestBody: RequestBody?): String{
return try {
val buffer = Buffer()
requestBody?.writeTo(buffer)
buffer.readUtf8()
} catch (e: IOException){
e.printStackTrace()
""
}
}
}
add a comment |
up vote
0
down vote
Resolved this issue with custom interceptors for OkHTTP client. So I've created custom interceptor that would analyze outgoing request and alter its body JSON data if it meets certain criteria.
okHttpClientBuilder.addInterceptor(CustomInterceptor(1))
Works like a charm!
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
class CustomInterceptor (private val version: Int): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestBody = request.body()
val subtype = requestBody?.contentType()?.subtype()
if(subtype != null
&& subtype.contains("json")) {
val bodyWithToken = addVersionParamToJSONBody(requestBody)
if(null != bodyWithToken){
val requestBuilder = request.newBuilder()
request = requestBuilder
.post(bodyWithToken)
.build()
}
}
return chain.proceed(request)
}
private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
val customRequest = bodyToString(requestBody)
return try{
val jsonObject = JSONObject(customRequest)
jsonObject.put("version", version)
RequestBody.create(requestBody?.contentType(), jsonObject.toString())
} catch (e: JSONException){
e.printStackTrace()
null
}
}
private fun bodyToString(requestBody: RequestBody?): String{
return try {
val buffer = Buffer()
requestBody?.writeTo(buffer)
buffer.readUtf8()
} catch (e: IOException){
e.printStackTrace()
""
}
}
}
add a comment |
up vote
0
down vote
up vote
0
down vote
Resolved this issue with custom interceptors for OkHTTP client. So I've created custom interceptor that would analyze outgoing request and alter its body JSON data if it meets certain criteria.
okHttpClientBuilder.addInterceptor(CustomInterceptor(1))
Works like a charm!
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
class CustomInterceptor (private val version: Int): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestBody = request.body()
val subtype = requestBody?.contentType()?.subtype()
if(subtype != null
&& subtype.contains("json")) {
val bodyWithToken = addVersionParamToJSONBody(requestBody)
if(null != bodyWithToken){
val requestBuilder = request.newBuilder()
request = requestBuilder
.post(bodyWithToken)
.build()
}
}
return chain.proceed(request)
}
private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
val customRequest = bodyToString(requestBody)
return try{
val jsonObject = JSONObject(customRequest)
jsonObject.put("version", version)
RequestBody.create(requestBody?.contentType(), jsonObject.toString())
} catch (e: JSONException){
e.printStackTrace()
null
}
}
private fun bodyToString(requestBody: RequestBody?): String{
return try {
val buffer = Buffer()
requestBody?.writeTo(buffer)
buffer.readUtf8()
} catch (e: IOException){
e.printStackTrace()
""
}
}
}
Resolved this issue with custom interceptors for OkHTTP client. So I've created custom interceptor that would analyze outgoing request and alter its body JSON data if it meets certain criteria.
okHttpClientBuilder.addInterceptor(CustomInterceptor(1))
Works like a charm!
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
class CustomInterceptor (private val version: Int): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestBody = request.body()
val subtype = requestBody?.contentType()?.subtype()
if(subtype != null
&& subtype.contains("json")) {
val bodyWithToken = addVersionParamToJSONBody(requestBody)
if(null != bodyWithToken){
val requestBuilder = request.newBuilder()
request = requestBuilder
.post(bodyWithToken)
.build()
}
}
return chain.proceed(request)
}
private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
val customRequest = bodyToString(requestBody)
return try{
val jsonObject = JSONObject(customRequest)
jsonObject.put("version", version)
RequestBody.create(requestBody?.contentType(), jsonObject.toString())
} catch (e: JSONException){
e.printStackTrace()
null
}
}
private fun bodyToString(requestBody: RequestBody?): String{
return try {
val buffer = Buffer()
requestBody?.writeTo(buffer)
buffer.readUtf8()
} catch (e: IOException){
e.printStackTrace()
""
}
}
}
answered Nov 7 at 19:18
Alexandr Zhurkov
757
757
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53194710%2fretrofit-add-field-dynamically-during-serialization%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can you expose your Retrofit API method declaration just to clarify a bit how you send the login data?
– pirho
Nov 8 at 9:41
Based on your answer you are using Kotlin or something. Maybe you update that tag in to your question. I created Java based Q&A here in case you want to try to apply that solution also.
– pirho
Nov 8 at 14:17