Posting JSON to REST API

后端 未结 9 827
-上瘾入骨i
-上瘾入骨i 2020-12-08 08:12

I\'m creating a REST API that will accept JSON requests.

I\'m testing it out using CURL:

curl -i -POST -H \'Accept: application/json\' -d \'{\"id\":1         


        
相关标签:
9条回答
  • 2020-12-08 09:03

    I experienced once and finally solved it by adding the jar file jackson-mapper-asl.jar. Go check if you have included all these dependencies although the exception itself does not tell u that.

    And you really don't need to explicitly configure the bean, and you don't need to put "consumes" in @RequestMapping statement. I'm using Spring 3.1 btw.

    contentType : "application/json" is the only one you need to configure. yes, client side.

    0 讨论(0)
  • 2020-12-08 09:04

    As sdouglass suggested, Spring MVC automatically detects Jackson and sets up a MappingJacksonHttpMessageConverter to handle conversion to/from JSON. But I did need explicity configure the converter to get it to work as he also pointed out.

    I added the following and my CURL GET requests were working..Hooray.

    AppConfig.java

    @Configuration
    @ComponentScan(basePackages = "com.app")
    public class AppConfig {
    
        @Bean
        public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()
        {
            final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
            final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
    
            HttpMessageConverter<?>[] httpMessageConverter = { mappingJacksonHttpMessageConverter };
    
            String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
    
            annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
            annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
    
            return annotationMethodHandlerAdapter;
        }
    }
    


    curl -i -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase
    
    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    Content-Type: application/json
    Transfer-Encoding: chunked
    Date: Thu, 26 Apr 2012 21:19:55 GMT
    
    [{"id":1,"pan":111}]
    



    But the following CURL POST was still not working (Never hitting the controller action and giving no console debug info.

    curl -i -X POST -H "Content-Type:application/json"  http://localhost:8080/PurchaseAPIServer/api/purchaseMe -d "{"id":2,"pan":122}"
    
    HTTP/1.1 400 Bad Request
    Server: Apache-Coyote/1.1
    Content-Type: text/html;charset=utf-8
    Content-Length: 971
    Date: Thu, 26 Apr 2012 21:29:56 GMT
    Connection: close
    
    The request sent by the client was syntactically incorrect ().
    



    So I added Logback to get some detailed debugging started.

    <configuration>
    
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <file>/home/thomas/springApps/purchaseapi.log</file>
            <encoder>
                <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <logger name="org.hibernate" level="DEBUG" />
    
        <logger name="org.springframework" level="TRACE" />
        <logger name="org.springframework.transaction" level="INFO" />
        <logger name="org.springframework.security" level="INFO" /> <!-- to debug security related issues (DEBUG) -->
        <logger name="org.springframework.web.servlet.mvc" level="TRACE" /> <!-- some serialization issues are at trace level here: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod -->
    
        <!-- our service -->
        <logger name="com.app" level="DEBUG" />
        <!-- <logger name="com.app" level="INFO" /> --><!-- to follow if setup is being executed -->
    
        <root level="INFO">
            <appender-ref ref="FILE" />
        </root>
    
    </configuration>
    



    Adding TRACE level debugging to org.springframework.web.servlet.mvc gave me the answer to the problem.

    2012-04-28 14:17:44,579 DEBUG [http-bio-8080-exec-3] o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor [AbstractMessageConverterMethodArgumentResolver.java:117] Reading [com.app.model.Purchase] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter@74a14fed]
    2012-04-28 14:17:44,604 TRACE [http-bio-8080-exec-3] o.s.w.s.m.m.a.ServletInvocableHandlerMethod [InvocableHandlerMethod.java:159] Error resolving argument [0] [type=com.app.model.Purchase]
    HandlerMethod details: 
    Controller [com.app.controller.PurchaseController]
    Method [public void com.app.controller.PurchaseController.create(com.app.model.Purchase)]
    
    org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unexpected character ('p' (code 112)): was expecting double-quote to start field name
    



    I changed my CURL POSTs to the following an it all worked:

    curl -i -X POST -H "Content-Type:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase -d '{"pan":11111}'
    HTTP/1.1 201 Created
    Server: Apache-Coyote/1.1
    Content-Length: 0
    Date: Sat, 28 Apr 2012 13:19:40 GMT
    

    Hopefully someone finds this useful.

    0 讨论(0)
  • 2020-12-08 09:05

    Its 2014 and I wanted to add a few updates to this question which helped me solve the same problem.

    1. Code update to replace deprecated AnnotationMethodHandlerAdapter in Spring 3.2

          @Configuration
          public class AppConfig {
      
      
          @Bean
          public RequestMappingHandlerAdapter  annotationMethodHandlerAdapter()
          {
              final RequestMappingHandlerAdapter annotationMethodHandlerAdapter = new RequestMappingHandlerAdapter();
              final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
      
              List<HttpMessageConverter<?>> httpMessageConverter = new ArrayList<HttpMessageConverter<?>>();
              httpMessageConverter.add(mappingJacksonHttpMessageConverter);
      
              String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
      
              annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
              annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
      
              return annotationMethodHandlerAdapter;
          }
      }
      
    2. HTTP/1.1 415 Unsupported Media Type error

    After spending many hours trying to figure out why I am STILL GETTING a 415 error even after adding the correct JSON configuration I finally realized that the problem was NOT with the server side but with the client side. In order for Spring to accept your JSON you MUST make sure that you are sending both "Content-Type : application/json" and "Accept: application/json" as part of your http headers. for me specifically it was an android application HttpUrlConnection which I had to set as:

        public static String doPost(final String urlString,final String requestBodyString) throws IOException {
            final URL url = new URL(urlString);
    
            final HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            try {
              urlConnection.setReadTimeout(10000 /* milliseconds */);
              urlConnection.setConnectTimeout(15000 /* milliseconds */);
              urlConnection.setRequestProperty("Content-Type", "application/json");
              urlConnection.setRequestProperty("Accept", "application/json");
              urlConnection.setDoOutput(true);
              urlConnection.setRequestMethod("POST");
              urlConnection.setChunkedStreamingMode(0);
    
              urlConnection.connect();
    
              final PrintWriter out = new PrintWriter(urlConnection.getOutputStream());
              out.print(requestBodyString);
              out.close();
    
              final InputStream in = new BufferedInputStream(urlConnection.getInputStream());
              final String response =  readIt(in);
    
              in.close(); //important to close the stream
    
              return response;
    
            } finally {
              urlConnection.disconnect();
            }
        }
    
    0 讨论(0)
提交回复
热议问题