Reputation: 171
Could you tell me how to pass sort param to rest controller in snake_case format?
My entity class
@Entity
public class MyEntity extends BaseEntity{
@Id
private Long id;
@Column
private Long parentId;
}
Controller method
@GetMapping("list")
List<MyEntity> getEntityList(
@PageableDefault(sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable);
}
In request i want to use ?sort=parent_id
I've created Jackson2ObjectMapperBuilder and it builds correct snake_case json
But spring send me Caused by: org.springframework.data.mapping.PropertyReferenceException: No property parent found for type MyEntity! Did you mean 'parentId'?
I think this is issue about parsing because spring cut everything after '_' symbol.
I've tried:
Upvotes: 3
Views: 919
Reputation: 171
I solved the problem. For correct working with snake_case parameter values we need to create custom OncePerRequestFilter. This filter prepare params before passing to controller.
User nullptr used same way here. By the way, using filter you can prepare any other params/values but this solution may produce mistakes. All requests will go through the filter.
@Configuration
public class SnakeCaseFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final Map<String, String[]> formattedParams = new ConcurrentHashMap<>();
//Convert values for each parameter
for (String param : request.getParameterMap().keySet()) {
String[] values = request.getParameterValues(param);
String formattedParam = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, param);
formattedParams.put(formattedParam, values);
}
filterChain.doFilter(new CustomResponseWrapper(request, formattedParams), response);
}
/**
* Wrapper return new formatted parameters
*/
class CustomResponseWrapper extends HttpServletRequestWrapper {
/**
* Constructs a request object wrapping the given request.
*
* @param request the {@link HttpServletRequest} to be wrapped.
* @throws IllegalArgumentException if the request is null
*/
private Map<String, String[]> params;
public CustomResponseWrapper(HttpServletRequest request, Map<String, String[]> params) {
super(request);
this.params = params;
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
}
}
Upvotes: 1