2013-05-09 11 views
28

मैं एक स्प्रिंग एमवीसी प्रोजेक्ट पर काम कर रहा हूं और मुझे जो कार्यों की आवश्यकता है, उनमें से एक मुझे POST अनुरोध में उपयोगकर्ता द्वारा भेजे गए JSON डेटा की एक स्ट्रिंग की आवश्यकता है। मुझे पता है कि वसंत वस्तुओं के लिए जैक्सन का उपयोग कर JSON deserialize होगा, लेकिन अगर मैं की तरह कुछ कोशिश निम्नलिखित:स्प्रिंग एमवीसी: जेएसओएन अनुरोध निकाय को deserialize

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

मैं बस वापस HTTP 400 ग़लत अनुरोध प्राप्त ("। अनुरोध ग्राहक द्वारा भेजे गए वाक्य रचना गलत थी") ।

क्लाइंट द्वारा स्ट्रिंग के रूप में भेजे गए कच्चे JSON को मैं कैसे प्राप्त कर सकता हूं?

+1

सर्वर लॉग में कोई भी स्टैकट्रैक क्या है और आपने यह अनुरोध कैसे किया है, जेएस कोड भी पोस्ट करें !!! AJAX कोड पोस्ट करें .. – NINCOMPOOP

+0

@NoobUnChained - मैं हूँ एक आरईएसटी एपीआई का परीक्षण करने के लिए क्रोम एक्सटेंशन के माध्यम से खुद को अनुरोध कर रहा हूं ई का कोई स्टैकट्रैक आउटपुट नहीं है। @ alex23 - मैं इसे एक स्ट्रिंग के रूप में स्पष्ट रूप से संसाधित करने के लिए कैसे कहूं? मैं गारंटी नहीं दे सकता कि प्रत्येक ग्राहक 'सामग्री-प्रकार: एप्लिकेशन/टेक्स्ट' हेडर भेज देगा। –

उत्तर

45

आपको आमतौर पर इस प्रकार की त्रुटि दिखाई देगी जब स्प्रिंग एमवीसी को एक अनुरोध मैपिंग मिलती है जो यूआरएल पथ से मेल खाता है लेकिन पैरामीटर (या हेडर या कुछ) हैंडलर विधि की अपेक्षा नहीं करते हैं।

यदि आप @RequestBody एनोटेशन का उपयोग करते हैं तो मेरा मानना ​​है कि स्प्रिंग एमवीसी एक अनुरोध के लिए POST अनुरोध के पूरे शरीर को मानचित्र करने की उम्मीद कर रहा है। मुझे लगता है कि आपका शरीर बस एक स्ट्रिंग नहीं है, लेकिन कुछ पूर्ण JSON ऑब्जेक्ट है।

आप JSON ऑब्जेक्ट आप उम्मीद कर रहे हैं तो आप देखेंगे कि आपके DoSomething घोषणा में साथ स्ट्रिंग पैरामीटर को बदलना सकता है की एक जावा मॉडल,

public void doSomething(@RequestBody MyObject myobj) {

इस तरह के रूप में आप एक जावा नहीं है, तो है, तो ऑब्जेक्ट जो JSON से मेल खाता है तो आप String प्रकार को Map<String, Object> के साथ बदलकर काम कर सकते हैं और देख सकते हैं कि यह आपको एक समाधान समाधान के करीब ले जाता है या नहीं।

आप स्प्रिंग एमवीसी में डीबग लॉगिंग भी चालू कर सकते हैं ताकि यह एक बुरा अनुरोध क्यों हो सके।

संपादित करें: टिप्पणी में अपनी आवश्यकताओं को देखते हुए, आप बस HttpServletRequest अपने विधि में इंजेक्षन और शरीर अपने आप को पढ़ सकता है।

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

आप सही हैं - शरीर एक पूर्ण JSON ऑब्जेक्ट है। मैं सामान्य रूप से इसे जावा ऑब्जेक्ट पर मैप कर दूंगा लेकिन ऑब्जेक्ट बनाने से पहले मुझे कच्चे JSON को संशोधित करने की आवश्यकता है, इसलिए मुझे कच्चे JSON स्ट्रिंग की आवश्यकता क्यों है। –

+0

टिप्पणी को दोबारा करने के लिए खेद है, लेकिन मैं अपनी उपरोक्त टिप्पणी संपादित नहीं कर सकता। मैंने स्प्रिंग में डीबग लॉगिंग सक्षम की और इस अपवाद के साथ आया: 'org.codehaus.jackson.map.JsonMappingException: जेएसओएन नहीं पढ़ सका: java.lang के उदाहरण को deserialize नहीं कर सकता। START_ARRAY टोकन से बाहर स्ट्रिंग - तो मैं कैसे छोड़ूँगा deserializing भाग और बस एक स्ट्रिंग के रूप में JSON डेटा पुनर्प्राप्त? –

+0

यदि आप इसे एक स्ट्रिंग के रूप में चाहते हैं तो आपको इसे स्ट्रिंग के रूप में भेजना चाहिए। सिर्फ इसलिए कि स्ट्रिंग में JSON सामग्री शामिल है इसका मतलब यह नहीं है कि आपको स्प्रिंग एमवीसी को बताना होगा। @RequestBody का उपयोग न करें, और एक फॉर्म में नियमित अनुरोध param के रूप में जेसन मान भेजें। – digitaljoel

2

आप @RequestBody पूरी तरह से परहेज की कोशिश कर सकते हैं और इसके बजाय एक InputStream/Reader या एक WebRequest/HttpServletRequest के माध्यम से सीधे अनुरोध शरीर हड़पने।

1

मेरे मामले में ऐसा इसलिए है क्योंकि जेसन ने फील्ड नामों का हवाला नहीं दिया है। एक उदाहरण है, यह स्वीकार नहीं किया है:

{ entity: "OneEntity"} 

लेकिन यह एक हाँ:

{ "entity": "OneEntity"} 

मैं नहीं मिला है अभी तक कैसे मैं वसंत संदर्भ में वस्तु मानचित्रण कॉन्फ़िगर कर सकते हैं। मुझे पता है कि एक JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES है लेकिन मुझे नहीं पता कि ऑब्जेक्ट मैपर के लिए यह कैसे सेट करें।

4

हम एक स्थिति है जहाँ हम कुछ नियंत्रक तरीकों सेम, और अन्य तरीकों जहां हम सिर्फ कच्चे स्ट्रिंग चाहता था पोस्ट शरीर मैप करने के लिए मिल गयी। @RequestBodyएनोटेशन का उपयोग करके इसे पूरा करने के लिए, आपको एकाधिक संदेश कन्वर्टर्स को कॉन्फ़िगर करने की आवश्यकता है, जैसे कुछ ...

<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> 

फिर, विभिन्न तरीकों जाने का अनुरोध करने के लिए एक उपयुक्त मान के साथ "सामग्री प्रकार" शीर्षक निर्दिष्ट करना होगा। उन तरीकों के लिए जहां अनुरोध निकाय को मैक्सबी बीन पर मैप किया गया है, "application/xml" निर्दिष्ट करें। और उन लोगों के लिए जहां अनुरोध निकाय स्ट्रिंग है, "text/plain" का उपयोग करें।

0

यदि आपका सामग्री-प्रकार "एप्लिकेशन/जेसन" है और आपका पहला संदेश कनवर्टर org.springframework.http.converter.StringHttpMessageConverter नहीं है, वसंत सही काम नहीं कर सका। मेरे मामले में, मैं ऐसा किया: वसंत संस्करण के साथ

<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

मेरे लिए अद्यतन यह बस एक "आवश्यक अब ।" XXX "के बजाय XXX था और सब कुछ ठीक आपके पास के रूप में काम कर रहा है यह सामग्री-प्रकार अनुप्रयोग/जेसन

संबंधित मुद्दे