I have API method mapping like this
@POST("api/updateStarted/{id}/{started}")
suspend fun updateStarted(
@Path("id") id: Int,
@Path("started") started: Date
) : Response <Int>
I want to use yyyy-MM-dd'T'HH:mm:ss
format everywhere. My API adapter looks like this:
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val apiClient: ApiClient = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson.create()))
.baseUrl(API_BASE_URL)
.client(getHttpClient(API_USERNAME, API_PASSWORD))
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiClient::class.java)
However GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
cannot affect date format when I pass it thru URL (because that's not JSON) so Retrofit builds URL like this:
http://myserver.com/api/updateFinished/2/Fri Jan 27 13:48:42 GMT 01:00 2023
instead of something like this:
http://myserver.com/api/updateFinished/2/2023-01-28T02:03:04.000
How can I fix that? I'm new in Retrofit and I don't fully understand date/time libraries in Java.
CodePudding user response:
GsonConverterFactory
supports responseBodyConverter
and requestBodyConverter
which aren't used to convert URL params. For that, you need a stringConverter
which, fortunately is trivial to implement:
class MyToStringConverter : Converter<SomeClass, String> {
override fun convert(value: SomeClass): String {
return formatToUrlParam(value)
}
companion object {
val INSTANCE = MyToStringConverter()
}
}
class MyConverterFactory : Converter.Factory() {
override fun stringConverter(type: Type, annotations: Array<out Annotation>, retrofit: Retrofit): Converter<*, String>? {
return if (type == SomeClass::class.java) {
//extra check to make sure the circumstances are correct:
if (annotations.any { it is retrofit2.http.Query }) {
MyToStringConverter.INSTANCE
} else {
null
}
} else {
null
}
}
}
I've added checking for annotations as example if one would want tighter control on when the converter is used.
CodePudding user response:
You can switch the data type from java.util.Date
to java.time.LocalDateTime
if you want your desired format using the toString()
method of that data type.
Currently, you have Date.toString()
producing an undesired result.
If you don't have to use a Date
, import java.time.LocalDateTime
and just change your fun
a little to this:
@POST("api/updateStarted/{id}/{started}")
suspend fun updateStarted(
@Path("id") id: Int,
@Path("started") started: LocalDateTime
) : Response <Int>