3

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:

  • @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
  • @Column(name = "parent_id") @JsonProperty("parent_id")
  • @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

1 Answer 1

1

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);
        }

    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

You need to change the case of the value, but did it for the parameter name :) How is this supposed to work?
@Vijit In my case I needed to cast into snake case key, not value. By default spring use camelCase keys I needed ?sort=parent_id instead of ?sort=parentId The code in answer is fix that
Oh.. Obviously I missed the point )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.