2011-12-11 13 views
13

स्प्रिंग एमवीसी का उपयोग करके एक विश्वसनीय वेब सेवा का निर्माण करते समय, मुझे लगता है कि जैक्सन जेएसओएन deserialization और जेएसआर -303 बीन सत्यापन गठबंधन करने की कोशिश करते समय मुझे एक मुश्किल स्थिति का सामना करना पड़ा।मैं जेएसआर -303 सत्यापन और जैक्सन जेएसओएन मैपिंग को प्रभावी ढंग से कैसे समर्थन कर सकता हूं?

जेएसआर -303 सत्यापन के बारे में साफ-सुथरा चीजों में से एक यह है कि कोई भी पहली बाधा उल्लंघन पर असफल होने के बजाय लक्षित ऑब्जेक्ट से जुड़े सभी सत्यापन त्रुटियों को वापस कर सकता है (हालांकि यदि आप इसका उपयोग करना चाहते हैं तो एक असफल फास्ट मोड है)।

जहां इस तरह के रूप एक JSON पेलोड है एक परिदृश्य की कल्पना कीजिए:

{ 
    "firstname": "Joe", 
    "surname": "Bloggs", 
    "age": 25 
} 

और फिर आप वस्तु पर आप मैप करना चाहते हैं:

public class Person { 

    @NotNull 
    private String firstname; 

    @NotNull 
    private String surname; 

    @Min(value = 0) 
    private int age; 

    ... 
} 

इस सेटअप के साथ मेरी समस्या यह है कि यदि है ग्राहक "उम्र" के लिए मूल्य के रूप में एक स्ट्रिंग भेजता है, पूरे जैक्सन deserialization प्रक्रिया विशेष रूप से कारण विफल करने के कारण लक्षित करने में विफल हो जाएगा (यानी हम कभी भी मान्य होने तक कभी नहीं मिलेगा)। कल्पना कीजिए, फिर, यह पेलोड:

{ 
    "age": "invalid" 
} 

इस मामले में, मैं वापस जाने के लिए किया जाएगा चाहते हैं, उसे एक "त्रुटि" प्रतिक्रिया जैसे:

{ 
    "errors" : [ 
     "error": { 
     "field": "firstname", 
     "message": "Must not be null", 
     }, 
     "error": { 
     "field": "surname", 
     "message": "Must not be null", 
     }, 
     "error": { 
     "field": "age", 
     "message": "Must be numeric value greater than or equal 0", 
     } 
    ] 
} 

इस समस्या को हल आसान तरीका होगा बस "स्ट्रिंग" प्रकार के रूप में "आयु" फ़ील्ड निर्दिष्ट करने के लिए और फिर स्थिरता परत कहें, इसे मानते समय मान को रूपांतरित करें। हालांकि, मुझे वास्तव में डेटा ट्रांसफर ऑब्जेक्ट्स का उपयोग करने का विचार पसंद नहीं है जो एक कंबल फैशन में स्ट्रिंग का उपयोग करता है - यह एक साफ डिजाइन को संरक्षित करने के मामले में ऐसा करने में गलत लगता है।

एक अन्य विकल्प मैं के बारे में सोचा के रूप में एक वर्ग बनाने के लिए होगा:

public abstract class BindableValue<T> { 

    private String stringValue; 

    private T value; 

    public T getValue() { 
     if(value == null) { 
     value = fromString(stringValue); 
     } 
     return value; 
    } 

    protected abstract T fromString(String stringValue); 
} 

मैं तो इस तरह के IntegerValue, LongValue, DateTimeValue आदि के रूप में कार्यान्वयन निश्चित रूप से भी जैक्सन के लिए कस्टम प्रकार एडेप्टर लेखन बना सकते हैं। और फिर मेरी व्यक्ति वर्ग हो सकता है:

public class Person { 

    @NotNull 
    private StringValue firstname; 

    @NotNull 
    private StringValue surname; 

    @Min(value = 0) 
    private IntegerValue age; 

    ... 
} 

यह लगभग मैं क्या चाहते हैं, लेकिन, दुर्भाग्य से, इस तरह के @NotNull और @min रूप JSR-303 एनोटेशन नहीं मेरी BindableValue कार्यान्वयन पहचान करने के लिए जा रहे हैं है।

तो, क्या कोई इस तरह की समस्या को क्लीनर तरीके से हल कर सकता है?

उत्तर

2

मुझे एहसास है कि ऐसा करने का सबसे अच्छा तरीका केवल सभी क्षेत्रों के लिए स्ट्रिंग का उपयोग करना है, लेकिन उस तथ्य को समाहित करना और अभी भी टाइप विशिष्ट विधि सेटर्स और गेटर्स प्रदान करना है। जैसे

public class Person { 

    @NotNull 
    private String name; 

    @NotNull 
    @Min(value = 0) 
    private String age; 

    public String getName() { 
     return name; 
    } 

    public Integer getAge() { 
     return age != null ? new Integer(age) : null; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public void setAge(Integer age) { 
     this.age = age == null ? null : String.valueOf(age); 
    } 

    @JsonSetter 
    private void setAge(String age) { 
     this.age = age; 
    } 
} 

इस तरह, मुझे यह व्यवहार मिलता है जब मैं सार्वजनिक ऑब्जेक्ट इंटरफ़ेस को अभी भी "साफ" सुनिश्चित करता हूं।

1

एक और संभावना है कि अज्ञात गुणों पर जैक्सन की शिकायतों को अक्षम करने के लिए (this विकी पेज देखें), अपरिचित चीज़ों को "ड्रॉप" करने के लिए, और बाध्य होने वाली चीज़ों को मान्य करने के लिए। आप वैकल्पिक रूप से अपरिचित गुणों के लिए श्रोता को भी परिभाषित कर सकते हैं। और फिर आप बाध्य होने वाले डेटा को सत्यापित करने के लिए बीन सत्यापन का उपयोग कर सकते हैं।

0

ठीक है, क्योंकि इसका अभी तक उल्लेख नहीं किया गया था ....DropWizard मुझे लगता है कि जाने का तरीका है - यह जैक्सन पर जेएक्स-आरएस (जर्सी) को बीन वैलिडेशन (हाइबरनेट इम्प्ल्यू मुझे लगता है) के साथ जोड़ता है, और यह सब "बस काम करता है"।

+0

मैं साधारण परीक्षण किया जाता है और यदि आप नहीं एक नंबर मूल्य के साथ drewzilla के पहले पद से json भेज आपको मिलता है: { "कोड": 400, "message": "JSON कार्रवाई करने में अक्षम"}। तो ड्रॉपविज़ार्ड इस समस्या को हल नहीं करता है। – wjtk

+0

मेरी टिप्पणी पोस्ट के संबंध में मूल रूप में थी। DropWizard बीन सत्यापन के अर्थशास्त्र को नहीं बदलता है, लेकिन यह इस बात को हल करता है कि कोई इसका उपयोग कैसे सक्षम करता है। वसंत जैसे अन्य ढांचे इस बिंदु पर भी इसे प्रदान कर सकते हैं। लेकिन मूल टिप्पणी के समय पर ध्यान दें। – StaxMan

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