Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save xexes/28808b15a3102ff40840093464575d1a to your computer and use it in GitHub Desktop.
Save xexes/28808b15a3102ff40840093464575d1a to your computer and use it in GitHub Desktop.
package com.example.custombodyannotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class CustomBodyAnnotationApplication {
public static void main(String[] args) {
SpringApplication.run(CustomBodyAnnotationApplication.class, args);
}
@Bean
WebMvcConfigurer webMvcConfigurer(ObjectMapper objectMapper) {
return new WebMvcConfigurer() {
@Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new JsonParameterHandlerMethodArgumentResolver(objectMapper));
}
};
}
}
class JsonParameterHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
private final ObjectMapper objectMapper;
JsonParameterHandlerMethodArgumentResolver(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(JsonParameter.class);
}
@Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
JsonParameter parameterAnnotation = parameter.getParameterAnnotation(JsonParameter.class);
HttpInputMessage inputMessage = this.createInputMessage(webRequest);
JsonNode jsonNode = objectMapper.readTree(inputMessage.getBody());
return jsonNode.get(parameterAnnotation.value()).asText();
}
private ServletServerHttpRequest createInputMessage(NativeWebRequest webRequest) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Assert.state(servletRequest != null, "No HttpServletRequest");
return new ServletServerHttpRequest(servletRequest);
}
}
@RestController
class HelloCtrl {
@PostMapping("/foo")
void foo(@JsonParameter("title") String title) {
System.out.println(title);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@interface JsonParameter {
String value();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment