1

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 ?

Ludovic C
  • 2,855
  • 20
  • 40
  • Jersey's `@QueryParam` does not recognize deep-object parameters. But it is possible to register your own annotation to handle this. Take a look at this excellent answer by Paul Samsotha: https://stackoverflow.com/a/66426398/106350 – ivant Mar 02 '21 at 10:01

0 Answers0