We have problems deserializing a query parameter with square bracket notation (?paging[offset]=3
) in Jersey.
We're using Jersey JAX-RS and annotating our endpoints and beans with swagger OpenAPI, and have tooling to generate our documentation automatically. We want to follow the JSON:API
standard for describing a new API. JSON:API
specifies that to implement paging, the API must accept a query parameter in the format : ?paging[offset]=0&paging[limit]=10
Our swagger annotations support this out of the box, allowing us to specify
@Parameter(
description = "paging",
style = ParameterStyle.DEEPOBJECT,
explode = Explode.TRUE)
Which is compatible with the square bracket notation paging[offset]
and so on. And it generates the correct documentation for our paging
parameter. All is good and great and dandy.
JAX-RS is the problem. There's a @QueryParam
annotation in JAX-RS. But, to use a complex object with the @QueryParam
annotation, that type must have a constructor with a single String parameter
. No problem. Let's add a constructor to our paging bean.
public class PagingBean {
public PagingBean(String stringValue){...}
@XmlElement
public getOffset(){...}
public setOffset(int offset){...}
@XmlElement
public getLimit(){...}
public setLimit(int limit){....}
}
So our endpoint now looks like
@Get("/path")
public Response someEndpoint(
@Parameter(description = "paging",style = ParameterStyle.DEEPOBJECT,explode = Explode.TRUE) @QueryParam("paging") PagingBean paging
){
...
}
But if we hit our api with
GET /rest/path?paging[limit]=10&paging[offset]=5
We can see that the paging
request parameter is null. It seems like Jersey didn't even recognize that the paging[...
is part of the paging
QueryParam
. Probably that it expects exactly the paging
key, and not a paging\[?
-like key.
We can confirm this by injecting a @Context UriInfo ui
and checking the request parameters. Their key are paging[offset]
and paging[limit]
One solution to this is to flatten
our parameters in the endpoint like so
@QueryParam("paging[limit]") pagingLimit,
@QueryParam("paging[offset]") pagingOffset
But this is not very nice to look at.
Ideas on how to deserialize this in Jersey ?