Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update @url path with different path parameters

Android - retrofit 2.9.0

I have the following retrofit method. I am using the @Url to include the base url and the path to search for products. However, I need to pass a code as part of the path. As I need to include the fullpath how can I add the code into the full url path?

"https://myBaseUrl/v2/products/{code}/search"

@GET
fun searchProductV2(
    @Path("code") storeCode: String,
    @Url fullPath: String = "https://myBaseUrl/v2/products/{code}/search",
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>
like image 960
ant2009 Avatar asked Feb 22 '26 06:02

ant2009


2 Answers

What you are trying won't work because if you specify @Url, it expects a static URL, it won't take @Path into consideration.

Solution 1

Remove the @Path parameter and just send the formatted string in @Url.

your method declaration will look like this:

@GET
fun searchProductV2(
    @Url fullPath: String,
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>

and your fullPath parameter can be initialized like this:

val fullPath = "https://myBaseUrl/v2/products/%s/search".format("storeCode")

Solution 2

A better approach would be to not use String as the @Url parameter. (@Url can be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri)

Here's an example using android.net.Uri:

your method declaration will look like this:

@GET
fun searchProductV2(
    @Url fullPath: Uri,
    @Query("searchCriteria[pageSize]") pageSize: String,
    @QueryMap apiSearchCriteria: Map<String, String>,
    @HeaderMap headerMap: Map<String, String> = emptyMap()
): Single<Products>

and your fullPath parameter can be initialized like this:

val fullPath = Uri.parse("https://myBaseUrl/v2/products/%s/search".format("storeCode"))

To make this code more nicer, you can create a helper class:

class DynamicUrl(private val formatString: String, private vararg val args: Any?) {
    fun toUri(): Uri = Uri.parse(formatString.format(*args))
}

and now your fullPath parameter can be initialized like this:

val fullPath = DynamicUrl("https://myBaseUrl/v2/products/%s/search", "storeCode").toUri()
like image 139
Sarthak Mittal Avatar answered Feb 24 '26 22:02

Sarthak Mittal


Define the URL template with the @GET annotation
... and then substitute with the @Path annotation:

@GET("{baseUrl}products/{storeCode}/search")
fun searchProductV2(
    @Path("baseUrl") baseUrl: String = "https://myBaseUrl/v2/",
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

Passing a constant value is also possible there:

@GET(Constants.API_BASE_URL_V2 + "products/{storeCode}/search")
fun searchProductV2(
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

Or just the version v2, assuming a BASE_URL of https://myBaseUrl/. No matter how these are being combined, it needs to be a String, a constant value or a @Path, nothing else is permitted:

@GET(Constants.API_VERSION_V2 + "/products/{storeCode}/search")
fun searchProductV2(
    @Path("storeCode") storeCode: String = "default",
    ...
): Single<Products>

Generally speaking, there is no other way. This is because no parameter can be used as a substitution for another one parameter. This code doesn't run, but is only the interface definition, from which the corresponding runtime classes are being generated from - that's why trying to add custom code is pointless.

Not sure what Single<Products> is, but the default (unmapped / raw) return type would be Call<ResponseBody> in Java. The model class/es used for ORM (with GSON or Moshi converter) can use @SerializedName() to map the field names.

like image 43
Martin Zeitler Avatar answered Feb 24 '26 20:02

Martin Zeitler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!