2013-08-23 8 views
9

मेरा मूल प्रश्न: क्या ऐसा कुछ भी बनाया गया है जो पहले से ही यह स्वचालित रूप से करता है (लोकप्रिय पुस्तकालय/पैकेज का हिस्सा नहीं होना चाहिए)? मुख्य चीजें जिनके साथ मैं काम कर रहा हूं वे हैं स्प्रिंग (एमवीसी) और जैक्सन 2। (एक तरह से बदबू आ रही हैकिसी ऑब्जेक्ट को किसी यूआरआई में क्रमबद्ध कैसे करें?

  1. प्रत्येक वर्ग कि property=value& रूप में अपनी विशिष्ट गुण को धारावाहिक में एक विधि बनाएं क्योंकि यह तर्क दोहराव का एक समूह है, मुझे लगता है:

    मैं समझता हूँ वहाँ यह करने के लिए कुछ मैनुअल तरीके हैं)।

  2. कोई ऑब्जेक्ट स्वीकार करता है जो किसी ऑब्जेक्ट को स्वीकार करता है, और सभी गुणों को गतिशील रूप से पढ़ने के लिए प्रतिबिंब का उपयोग करता है (मुझे गेटर्स लगता है), और प्रत्येक प्राप्त करके स्ट्रिंग का निर्माण करें। मुझे लगता है कि जैक्सन सामान्य रूप से क्रमबद्धता/deserialization के लिए कैसे काम करता है, लेकिन मैं वास्तव में नहीं जानता।
  3. ऑब्जेक्ट को क्रमबद्ध रूप से क्रमबद्ध करने के लिए जैक्सन की कुछ विशेषताओं का उपयोग करें। मैंने कस्टम सीरियलाइज़र का शोध किया है, लेकिन ऐसा लगता है कि वे एक वर्ग के लिए विशिष्ट हैं (इसलिए मुझे प्रत्येक कक्षा के लिए एक बनाना होगा जिसे मैं क्रमबद्ध करने की कोशिश कर रहा हूं), जबकि मैं एक सामान्य तरीके की उम्मीद कर रहा था। मुझे समझ में आ रहा है कि वस्तुओं को सार्वभौमिक रूप से कैसे लागू किया जाए। लिंक के कुछ:
  4. उपयोग ObjectMapper.convertValue(object, HashMap.class);, HashMap की कुंजी/मान जोड़े से अधिक पुनरावृति, और स्ट्रिंग निर्माण (जो अब मैं क्या उपयोग कर रहा हूँ, लेकिन मुझे लगता है कि रूपांतरण अत्यधिक हैं?)।
  5. मुझे लगता है कि ऐसे कुछ भी हैं जिनके बारे में मैं सोच नहीं रहा हूं।

मुख्य पोस्ट मैं देखा है Java: Getting the properties of a class to construct a string representation

मेरे बिंदु मैं कई वर्गों है कि मैं कुछ प्रत्येक के लिए विशिष्ट निर्दिष्ट किए बिना ही क्रमानुसार करने में सक्षम होना चाहते है कि है। यही कारण है कि मैं प्रतिबिंब (# 2 ऊपर) का उपयोग करके एक फ़ंक्शन सोच रहा हूं, इसे संभालने का एकमात्र तरीका है (यदि मुझे इसे मैन्युअल रूप से करना है)।

public class C1 { 
    private String C1prop1; 
    private String C1prop2; 
    private String C1prop3; 

    // Getters and setters for the 3 properties 
} 

public class C2 { 
    private String C2prop1; 
    private String C2prop2; 
    private String C2prop3; 

    // Getters and setters for the 3 properties 
} 

(नहीं, गुण नाम और सम्मेलनों नहीं क्या मेरे वास्तविक एप्लिकेशन द्वारा उपयोग की हैं, यह सिर्फ एक है:

यदि यह मदद करता है, मैं क्या मतलब का एक उदाहरण के साथ, कहते हैं, इन दो वर्गों है उदाहरण)

serializing के परिणामों C1prop1=value&C1prop2=value&C1prop3=value और C2prop1=value&C2prop2=value&C2prop3=value होगा, लेकिन वहाँ केवल एक ही जगह है कि परिभाषित करता है कि कैसे क्रमबद्धता होता है (पहले से ही कहीं परिभाषित, या मेरे द्वारा मैन्युअल रूप से बनाई गई) है।

तो मेरा विचार है कि मैं (पोस्ट से लिया मैं ऊपर लिंक) निम्न में से एक फार्म का उपयोग करके खत्म करना होगा:

public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    try { 
     Class c = Class.forName(this.getClass().getName()); 
     Method m[] = c.getDeclaredMethods(); 
     Object oo; 
     for (int i = 0; i < m.length; i++) 
     if (m[i].getName().startsWith("get")) { 
      oo = m[i].invoke(this, null); 
      sb.append(m[i].getName().substring(3) + ":" 
         + String.valueOf(oo) + "\n"); 
     } 
    } catch (Throwable e) { 
     System.err.println(e); 
    } 
    return sb.toString(); 
} 

और एक वस्तु को स्वीकार करने के इसे संशोधित, और स्वरूप बदलने StringBuilder में संलग्न वस्तुओं में से। यह मेरे लिए काम करता है, मुझे अब इसे संशोधित करने में मदद की ज़रूरत नहीं है।

तो फिर, मेरा मुख्य प्रश्न यह है कि अगर ऐसा कुछ है जो उपरोक्त फ़ंक्शन को संशोधित करने के लिए पहले से ही (संभावित रूप से सरल) क्रमबद्धता को संभालता है, भले ही मुझे प्रत्येक संपत्ति और मूल्य से निपटने के लिए निर्दिष्ट करना है और प्रत्येक को कैसे गठबंधन करना है?

यदि यह मदद करता है, तो इसकी पृष्ठभूमि यह है कि मैं एक अलग सर्वर पर एक GET अनुरोध करने के लिए RestTemplate (वसंत) का उपयोग कर रहा हूं, और मैं URL में किसी विशिष्ट ऑब्जेक्ट की गुण/मानों को पास करना चाहता हूं। मैं समझता हूं कि मैं कुछ उपयोग कर सकता हूं:

restTemplate.getForObject("URL?C1prop1={C1Prop1}&...", String.class, C1Object); 

मेरा मानना ​​है कि गुण स्वचालित रूप से मैप किए जाएंगे। लेकिन जैसा कि मैंने कहा, मैं प्रत्येक ऑब्जेक्ट प्रकार के लिए एक अलग यूआरएल टेम्पलेट और विधि बनाना नहीं चाहता हूं। मैं निम्नलिखित की तरह कुछ है करने के लिए आशा करती हूं कि:

public String getRequest(String url, Object obj) { 
    String serializedUri = SERIALIZE_URI(obj); 
    String response = restTemplate.getForObject("URL?" + serializedUri, String.class); 
    return response; 
} 

जहां SERIALIZE_URI वह जगह है जहाँ मैं इसे संभाल चाहते हैं। और मैं इसे getRequest("whatever", C1Object); और getRequest("whateverElse", C2Object); कह सकता हूं।

उत्तर

12

मुझे लगता है, समाधान संख्या 4 ठीक है। समझना और स्पष्ट करना आसान है।

मैं इसी तरह के समाधान का प्रस्ताव करता हूं जिसमें हम @JsonAnySetter एनोटेशन का उपयोग कर सकते हैं। कृपया, उदाहरण के नीचे देखें:

import com.fasterxml.jackson.annotation.JsonAnySetter; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class JacksonProgram { 

    public static void main(String[] args) throws Exception { 
     C1 c1 = new C1(); 
     c1.setProp1("a"); 
     c1.setProp3("c"); 

     User user = new User(); 
     user.setName("Tom"); 
     user.setSurname("Irg"); 

     ObjectMapper mapper = new ObjectMapper(); 
     System.out.println(mapper.convertValue(c1, UriFormat.class)); 
     System.out.println(mapper.convertValue(user, UriFormat.class)); 
    } 
} 

class UriFormat { 

    private StringBuilder builder = new StringBuilder(); 

    @JsonAnySetter 
    public void addToUri(String name, Object property) { 
     if (builder.length() > 0) { 
      builder.append("&"); 
     } 
     builder.append(name).append("=").append(property); 
    } 

    @Override 
    public String toString() { 
     return builder.toString(); 
    } 
} 

कार्यक्रम प्रिंट ऊपर:

prop1=a&prop2=null&prop3=c 
name=Tom&surname=Irg 

और अपने getRequest विधि ऐसा दिखाई दे सकता:

public String getRequest(String url, Object obj) { 
    String serializedUri = mapper.convertValue(obj, UriFormat.class).toString(); 
    String response = restTemplate.getForObject(url + "?" + serializedUri, String.class); 
    return response; 
} 
+3

होगा **। मैं निश्चित रूप से इसके साथ जाऊंगा, जब तक कि मैं अन्य सुझाव नहीं सुनता। मैं सहमत हूं कि # 4 बहुत अच्छा था - मुझे लगता है कि दृश्यों के पीछे यह # 2 है, इसलिए मैं इसे भी रख सकता हूं (सिवाय इसके कि मुझे वास्तव में यह समाधान पसंद है, इसलिए मैं इसका उपयोग करूंगा :))। – Ian

+0

मुझे यह सुनकर खुशी हुई। इसका इस्तेमाल करने के लिए स्वतंत्र महसूस करें। जैक्सन विश्वसनीय और तेज़ है इसलिए मुझे लगता है कि आपको जैक्सन लाइब्रेरी से जितना स्रोत कोड उतना उपयोग करना चाहिए। आपको यूआरएल एन्कोडिंग और अन्य सामानों के बारे में भी याद रखना चाहिए। –

+0

कूल, मैं इसकी सराहना करता हूं। यह जवाब ठीक वही है जो मैं खोज रहा था - जैक्सन की एक विशेषता जिसे मैं नहीं जानता था (क्योंकि मुझे पुस्तकालय के बारे में लगभग पर्याप्त जानकारी नहीं है, या उपयोग नहीं है)। मुझे नहीं पता कि यह लागू है या नहीं, लेकिन ऐसा लगता है कि '@ जेसन व्यू' का उपयोग करना एक और विकल्प हो सकता है। क्या आपको इस परिदृश्य में इसका उपयोग करने के बारे में कोई जानकारी है या क्यों नहीं (नहीं) इसका उपयोग आपके समाधान की तुलना में करें? – Ian

2

चलें हम c1 है।

c1.setC1prop1("C1prop1"); 
c1.setC1prop2("C1prop2"); 
c1.setC1prop3("C1prop3"); 

बहुत ** रोचक और शांत यूआरआई

UriComponentsBuilder.fromHttpUrl("http://test.com") 
      .queryParams(new ObjectMapper().convertValue(c1, LinkedMultiValueMap.class)) 
      .build() 
      .toUri()); 

में c1 में कनवर्ट करने के बाद हम

http://test.com?c1prop1=C1prop1&c1prop2=C1prop2&c1prop3=C1prop3 
+0

यह काम करता है, हालांकि, यह केवल तभी उपयोगी होता है जब आप वसंत ढांचे का उपयोग कर रहे हों या उन पुस्तकालयों तक पहुंच प्राप्त कर सकें। – njfife

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