2010-12-14 15 views
37

मैं JSON POST अनुरोधों को संभालने के लिए स्प्रिंग एमवीसी का उपयोग कर रहा हूं। कवर के नीचे मैं जैक्सन जेएसओएनएचटीपी मैसेज कनवर्टर का उपयोग कर रहा हूं जो जैक्सन जेएसओएन प्रोसेसर पर बनाया गया है और जब आप एमवीसी: एनोटेशन-संचालित का उपयोग करते हैं तो सक्षम है।वसंत और जैक्सन पूर्ण डेटा बाध्यकारी के साथ REST

@RequestMapping(value="/executeActions", method=RequestMethod.POST) 
    public @ResponseBody String executeActions(@RequestBody List<ActionImpl> actions) { 
     logger.info("executeActions"); 
     return "ACK"; 
    } 

मैं पाया है जैक्सन के नक्शे कि java.util.LinkedHashMap मदों की एक सूची के लिए requestBody (सरल डेटा बाइंडिंग):

अपनी सेवाओं में से एक कार्रवाई की एक सूची प्राप्त करता है। इसके बजाय, मैं अनुरोध टाइप की गई वस्तुओं की सूची (इस मामले में "ActionImpl") से बाध्य होना चाहता हूं।

मैं जानता हूँ कि यह करने के लिए आसान है अगर आप जैक्सन के ObjectMapper सीधे का उपयोग करें:

List<ActionImpl> result = mapper.readValue(src, new TypeReference<List<ActionImpl>>() { }); 

लेकिन मैं सोच रहा था सबसे अच्छा तरीका है इस लक्ष्य को हासिल करने के लिए क्या जब वसंत MVC और MappingJacksonHttpMessageConverter का उपयोग कर। कोई संकेत?

executeActions(@RequestBody TypeReference<List<ActionImpl>> actions) 

मैं इसे करने की कोशिश नहीं की है, लेकिन अपने प्रश्न के आधार पर यह पहली बात मैं कोशिश करेगा है:

धन्यवाद

उत्तर

27

मुझे संदेह है कि समस्या टाइप एरर के कारण है, यानी जेनेरिक पैरामीटर प्रकार को पारित करने के बजाय, शायद केवल action.getClass() पास हो गया है; और यह सूची <?> के बराबर प्रकार देगा।

public class ActionImplList extends ArrayList<ActionImpl> { } 

क्योंकि यह बनी रहेगी प्रकार की जानकारी भले ही वर्ग पारित हो जाता है:

अगर यह सही है, एक संभावना की तरह, एक मध्यवर्ती उप-वर्ग का उपयोग करने के लिए होगा। तो फिर:

public @ResponseBody String executeActions(@RequestBody ActionImplList actions) 

चाल करना होगा। इष्टतम नहीं है लेकिन काम करना चाहिए।

मुझे आशा है कि अधिक स्प्रिंग एमवीसी ज्ञान वाले किसी व्यक्ति को प्रकाश डाला जा सकता है कि क्यों पैरामीटर प्रकार पारित नहीं किया जा रहा है (शायद यह एक बग है?), लेकिन कम से कम एक काम है।

+1

आप सही हैं और जिस चाल का आपने प्रस्ताव दिया है वह काम करता है। बहुत बहुत धन्यवाद –

+2

यह समस्या स्प्रिंग 3.1 में हुई थी लेकिन वसंत 3.2 में तय की गई थी: https://jira.spring.io/browse/SPR-9570 – Martin

0

आप के रूप में विधि की घोषणा करने की कोशिश की है।

+0

अच्छा बिंदु, लेकिन यह काम नहीं करता है। जैक्सन टाइपरेंसेंस के उदाहरण के रूप में प्राप्त सूची को deserialize करने की कोशिश करता है और यह एक JsonMappingException पैदा करता है। –

2

यह प्रश्न पहले से ही पुराना है, लेकिन मुझे लगता है कि मैं वैसे भी योगदान कर सकता हूं।

StaxMan की तरह इंगित किया गया, यह टाइप एरर के कारण है। यह निश्चित रूप से होना चाहिए, क्योंकि आप विधि परिभाषा से प्रतिबिंब के माध्यम से सामान्य तर्क प्राप्त कर सकते हैं।

T read(Class<? extends T> clazz, HttpInputMessage inputMessage); 

यहाँ, केवल List.class विधि को दे दिया जाएगा: हालांकि, समस्या HttpMessageConverter की एपीआई है। इसलिए, जैसा कि आप देख सकते हैं, एक HttpMessageConverter को कार्यान्वित करना असंभव है जो विधि पैरामीटर प्रकार को देख कर वास्तविक प्रकार की गणना करता है, क्योंकि यह उपलब्ध नहीं है।

फिर भी, अपने स्वयं के कामकाज को कोड करना संभव है - आप बस HttpMessageConverter का उपयोग नहीं करेंगे। स्प्रिंग एमवीसी आपको अपना खुद का WebArgumentResolver लिखने की अनुमति देता है जो मानक रिज़ॉल्यूशन विधियों से पहले चलता है।उदाहरण के लिए आप अपनी खुद की कस्टम एनोटेशन (@JsonRequestBody?) का उपयोग कर सकते हैं जो आपके मान को पार्स करने के लिए सीधे ऑब्जेक्टमैपर का उपयोग करता है। आप विधि से पैरामीटर प्रकार प्रदान करने में सक्षम हो जाएगा:

final Type parameterType= method.getParameterTypes()[index]; 
List<ActionImpl> result = mapper.readValue(src, new TypeReference<Object>>() { 
    @Override 
    public Type getType() { 
     return parameterType; 
    } 
}); 

नहीं वास्तव में जिस तरह से TypeReference इरादा था इस्तेमाल किया जा रहा मुझे लगता है, लेकिन ObjectMapper एक अधिक उपयुक्त विधि प्रदान नहीं करता है।

41

मुझे पता चला है कि आप एक संग्रह के बजाय @RequestBody के रूप में सरणी का उपयोग कर प्रकार मिटाए गए मुद्दे के आसपास भी काम कर सकते हैं। उदाहरण के लिए, निम्नलिखित काम करेगा:

public @ResponseBody String executeActions(@RequestBody ActionImpl[] actions) { //... } 
+0

यह यहां प्रस्तुत लोगों का सबसे साफ काम है! – metadaddy

+1

मैं इसी तरह की समस्या पर फंस गया था, कोशिश की और यह काम करता है। हालांकि 3.1.1 को अपडेट करके। यहां तक ​​कि की सूची भी काम करेगी ... – sunny

+0

व्यवहार मनमानी है .. अभी भी उलझन में है – sunny

8

आपकी जानकारी के लिए, सुविधा स्प्रिंग 3.2 में उपलब्ध हो जाएगा (https://jira.springsource.org/browse/SPR-9570 देखें)

मैं सिर्फ वर्तमान M2 पर यह परीक्षण किया है और इसे से बाहर एक आकर्षण की तरह काम करता बॉक्स (पैरामीटरयुक्त प्रकार प्रदान करने के लिए अतिरिक्त एनोटेशन प्रदान करने की आवश्यकता नहीं है, इसे स्वचालित रूप से नए संदेश कनवर्टर द्वारा हल किया जाएगा)

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