2013-05-09 44 views
28

Tôi đang làm việc trên một dự án Spring MVC và một trong những nhiệm vụ tôi cần làm yêu cầu tôi phải có một chuỗi dữ liệu JSON được gửi bởi người dùng trong yêu cầu POST. Tôi biết rằng mùa xuân sẽ deserialize JSON sử dụng Jackson để các đối tượng, nhưng nếu tôi cố gắng một cái gì đó như sau:Spring MVC: Đừng deserialize JSON yêu cầu cơ thể

@RequestMapping(value = "/test", method = RequestMethod.POST) 
public void doSomething(@RequestBody String json) { 
    // do something 
} 

Tôi chỉ đơn giản là có được HTTP 400 Bad Request trở lại ("Yêu cầu gửi của khách hàng là cú pháp không chính xác") .

Làm cách nào để nhận được JSON thô được khách hàng gửi dưới dạng chuỗi?

+1

Stacktrace là gì nếu có trong nhật ký máy chủ và cách bạn thực hiện yêu cầu đó, đăng mã JS cũng như thế! Đăng mã AJAX .. – NINCOMPOOP

+0

@NoobUnChained - Tôi tự mình yêu cầu thông qua tiện ích mở rộng của Chrome để kiểm tra API REST. e không có đầu ra stacktrace. @ alex23 - Làm thế nào để tôi nói nó xử lý nó như một chuỗi một cách rõ ràng? Tôi không thể đảm bảo mọi khách hàng sẽ gửi tiêu đề 'Content-Type: application/text'. –

Trả lời

45

Bạn thường sẽ thấy loại lỗi này khi Spring MVC tìm thấy ánh xạ yêu cầu khớp với đường dẫn URL nhưng các tham số (hoặc tiêu đề hoặc thứ gì đó) không khớp với phương thức mà trình xử lý đang mong đợi.

Nếu bạn sử dụng chú thích @RequestBody thì tôi tin Spring MVC dự kiến ​​sẽ ánh xạ toàn bộ phần thân của yêu cầu POST tới một đối tượng. Tôi đoán cơ thể của bạn không chỉ đơn giản là một String, mà là một đối tượng JSON đầy đủ.

Nếu bạn có một mô hình java của đối tượng JSON bạn đang mong đợi thì bạn có thể thay thế các tham số String với điều đó trong tờ khai doSomething của bạn, chẳng hạn như

public void doSomething(@RequestBody MyObject myobj) {

Nếu bạn không có một Java đối tượng khớp với JSON thì bạn có thể cố gắng làm cho nó hoạt động bằng cách thay thế loại String bằng một số Map<String, Object> và xem điều đó có giúp bạn gần hơn với giải pháp làm việc hay không.

Bạn cũng có thể bật tính năng ghi nhật ký gỡ lỗi trong Spring MVC để biết thêm thông tin về lý do khiến đó là yêu cầu không hợp lệ.

Chỉnh sửa: Với yêu cầu của bạn trong các nhận xét, bạn có thể chỉ cần đưa HttpServletRequest vào phương thức của bạn và đọc chính cơ thể.

public void doSomething(HttpServletRequest request) { 
    String jsonBody = IOUtils.toString(request.getInputStream()); 
    // do stuff 
} 
+0

Bạn nói đúng - phần thân là một đối tượng JSON đầy đủ. Tôi thường sẽ ánh xạ nó tới một đối tượng Java nhưng tôi cần phải sửa đổi JSON thô trước khi tạo đối tượng, do đó tại sao tôi cần chuỗi JSON thô. –

+0

Xin lỗi để bình luận thêm, nhưng tôi không thể chỉnh sửa bình luận ở trên. Tôi đã bật gỡ lỗi đăng nhập vào Mùa xuân và đã đưa ra ngoại lệ này: 'org.codehaus.jackson.map.JsonMappingException: Không thể đọc JSON: Không thể deserialize thể hiện của java.lang.String trong START_ARRAY token' - vì vậy làm cách nào tôi bỏ qua phần deserializing và chỉ lấy dữ liệu JSON dưới dạng chuỗi? –

+0

Nếu bạn muốn nó như là một chuỗi sau đó bạn nên gửi nó như là một String. Chỉ vì String chứa nội dung JSON không có nghĩa là bạn cần báo cho Spring MVC biết. Không sử dụng @RequestBody và gửi giá trị json làm thông số yêu cầu thường xuyên trong biểu mẫu. – digitaljoel

2

Bạn có thể thử tránh @RequestBody hoàn toàn và thay vào đó lấy cơ thể yêu cầu trực tiếp thông qua một InputStream/Reader hoặc một WebRequest/HttpServletRequest.

1

Trong trường hợp của tôi là vì json chưa trích dẫn tên trường. Một ví dụ, điều này không được chấp nhận:

{ entity: "OneEntity"} 

nhưng một vâng này:

{ "entity": "OneEntity"} 

tôi đã không tìm thấy nhưng làm thế nào tôi có thể cấu hình ánh xạ đối tượng trong bối cảnh mùa xuân. Tôi biết có một JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES nhưng tôi không biết cách thiết lập cho trình ánh xạ đối tượng.

4

Chúng tôi đã có một tình huống mà chúng tôi muốn một số phương pháp điều khiển để lập bản đồ cơ thể POST để đậu, và các phương pháp khác, nơi mà chúng tôi chỉ muốn các nguyên Chuỗi. Để thực hiện việc này bằng cách sử dụng chú thích @RequestBody, bạn cần phải định cấu hình nhiều trình biến đổi tin nhắn, chẳng hạn như ...

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> 
    <property name="useDefaultSuffixPattern" value="false"/> 
</bean> 

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 
      <ref bean="jsonConverter" /> 
      <ref bean="marshallingConverter" /> 
      <ref bean="stringHttpMessageConverter" /> 
     </list> 
    </property> 
</bean> 

<bean id="jsonConverter" 
     class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="supportedMediaTypes" value="application/json" /> 
</bean> 

<bean id="marshallingConverter" 
     class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> 
    <constructor-arg ref="jaxb2Marshaller" /> 
    <property name="supportedMediaTypes" value="application/xml"/> 
</bean> 

<bean id="stringHttpMessageConverter" 
     class="org.springframework.http.converter.StringHttpMessageConverter"> 
    <property name="supportedMediaTypes" value="text/plain"/> 
</bean> 

Sau đó, yêu cầu các phương pháp khác nhau phải ghi rõ "content-type" tiêu đề với một giá trị thích hợp. Đối với những phương thức mà thân yêu cầu được ánh xạ tới một hạt JAXB JAXB, hãy chỉ định "application/xml". Và đối với những nơi thân yêu cầu là Chuỗi, hãy sử dụng "text/plain".

0

nếu loại nội dung của bạn là "application/json" và thông điệp đầu tiên của bạnChuyển đổi không phải là org.springframework.http.converter.StringHttpMessageConverter, Spring không thể hoạt động bình thường. Trong trường hợp của tôi, tôi đã làm điều này:

<mvc:annotation-driven> 
 
\t \t <mvc:message-converters> 
 
\t \t \t <ref bean="stringHttpMessageConverter" /><!-- 放在前面,对@RequestBody String json 提供支持 --> 
 
\t \t \t <ref bean="mappingJacksonHttpMessageConverter" /> 
 
\t \t </mvc:message-converters> 
 
\t </mvc:annotation-driven> 
 

 

 
\t <!-- 消息转换器 --> 
 
\t <bean id="stringHttpMessageConverter" 
 
\t \t class="org.springframework.http.converter.StringHttpMessageConverter"> 
 
\t \t <property name="supportedMediaTypes"> 
 
\t \t \t <list> 
 
\t \t \t \t <bean class="org.springframework.http.MediaType"> 
 
\t \t \t \t \t <constructor-arg index="0" value="text" /> 
 
\t \t \t \t \t <constructor-arg index="1" value="plain" /> 
 
\t \t \t \t \t <constructor-arg index="2" value="UTF-8" /> 
 
\t \t \t \t </bean> 
 
\t \t \t \t <bean class="org.springframework.http.MediaType"> 
 
\t \t \t \t \t <constructor-arg index="0" value="application" /> 
 
\t \t \t \t \t <constructor-arg index="1" value="json" /> 
 
\t \t \t \t \t <constructor-arg index="2" value="UTF-8" /> 
 
\t \t \t \t </bean> 
 
\t \t \t </list> 
 
\t \t </property> 
 
\t </bean> 
 

 
\t <bean id="mappingJacksonHttpMessageConverter" 
 
\t \t class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
 
\t \t <property name="supportedMediaTypes"> 
 
\t \t \t <list> 
 
\t \t \t \t <bean class="org.springframework.http.MediaType"> 
 
\t \t \t \t \t <constructor-arg index="0" value="text" /> 
 
\t \t \t \t \t <constructor-arg index="1" value="plain" /> 
 
\t \t \t \t \t <constructor-arg index="2" value="UTF-8" /> 
 
\t \t \t \t </bean> 
 
\t \t \t \t <bean class="org.springframework.http.MediaType"> 
 
\t \t \t \t \t <constructor-arg index="0" value="application" /> 
 
\t \t \t \t \t <constructor-arg index="1" value="json" /> 
 
\t \t \t \t \t <constructor-arg index="2" value="UTF-8" /> 
 
\t \t \t \t </bean> 
 
\t \t \t </list> 
 
\t \t </property> 
 
\t \t <!-- 设置时间格式, 有了这个就不用在pojo的属性上写了 --> 
 
\t \t <property name="objectMapper"> 
 
\t \t \t <bean class="com.fasterxml.jackson.databind.ObjectMapper"> 
 
\t \t \t \t <property name="dateFormat"> 
 
\t \t \t \t \t <bean class="java.text.SimpleDateFormat"> 
 
\t \t \t \t \t \t <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"></constructor-arg> 
 
\t \t \t \t \t </bean> 
 
\t \t \t \t </property> 
 
\t \t \t </bean> 
 
\t \t </property> 
 
\t </bean>

0

Đối với tôi với phiên bản mùa xuân cập nhật nó chỉ đơn giản là một "cần thiết bây giờ . 'XXX' thay vì XXX và tất cả mọi thứ đang làm việc tốt như bạn có Ứng dụng loại nội dung/json

Các vấn đề liên quan