स्प्रिंग RestTemplate के साथ JSON ऑब्जेक्ट्स की सूची प्राप्त करें


199

मेरे दो सवाल हैं:

  • स्प्रिंग रेस्टेमप्लेट का उपयोग करके JSON ऑब्जेक्ट्स की सूची कैसे मैप करें।
  • नेस्टेड JSON ऑब्जेक्ट्स को मैप कैसे करें।

मैं http://spring.io/guides/gs/consuming-rest/ से ट्यूटोरियल का अनुसरण करके https://bitpay.com/api/rates का उपभोग करने की कोशिश कर रहा हूं ।


2
इस उत्तर पर विचार करें, विशेष रूप से यदि आप जेनेरिक सूची का उपयोग करना चाहते हैं stackoverflow.com/questions/36915823/…
Moesio

जवाबों:


220

शायद इस तरह ...

ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(urlGETList, Object[].class);
Object[] objects = responseEntity.getBody();
MediaType contentType = responseEntity.getHeaders().getContentType();
HttpStatus statusCode = responseEntity.getStatusCode();

के लिए नियंत्रक कोड RequestMapping

@RequestMapping(value="/Object/getList/", method=RequestMethod.GET)
public @ResponseBody List<Object> findAllObjects() {

    List<Object> objects = new ArrayList<Object>();
    return objects;
}

ResponseEntityइसका एक एक्सटेंशन HttpEntityएक HttpStatusस्थिति कोड जोड़ता है । के RestTemplateरूप में अच्छी तरह से @Controllerइस्तेमाल किया। में RestTemplateइस वर्ग के द्वारा दिया जाता है getForEntity()और exchange()


यह एक आकर्षण की तरह काम करता है, धन्यवाद। हो सकता है कि आप मुझे कुछ अन्य ट्यूटोरियल या गाइड पर निर्देशित कर सकें जो मैं इस विषय पर पढ़ सकता था?
करुदी

2
कुछ कोड स्निपेट और उदाहरणों के लिए स्टैकओवरफ़्लो पर यहाँ देखने के लिए और ऑफिशियल स्प्रिंग वेबसाइट पर जाने के लिए ...... TblGps [] a = responseEntity.getBody ();
kamokaze

क्या जेनरिक का उपयोग करके यह संभव है? अर्थात मेरी विधि में एक क्लास है <T में Foo> पैरामीटर का विस्तार है और मैं GetForEityity विधि से T का संग्रह प्राप्त करना चाहूंगा।
डिस्क्यूटेंट

हां यह काम करना चाहिए, लेकिन आपके स्प्रिंग / जैकसन संस्करण और आपके वर्ग प्रकारों के आधार पर बॉक्स से बाहर नहीं हो सकता है। इसके सभी के बारे में क्रमिक / deserializing जेनरिक - http अनुरोध istself परवाह नहीं करता है कि क्या पहुँचाया जाता है।
कमोकॉज


335

पहले सरणी में वापस आने वाली इकाई को धारण करने के लिए किसी ऑब्जेक्ट को परिभाषित करें .. जैसे

@JsonIgnoreProperties(ignoreUnknown = true)
public class Rate {
    private String name;
    private String code;
    private Double rate;
    // add getters and setters
}

तब आप इस सेवा का उपभोग कर सकते हैं और इसके माध्यम से एक दृढ़ता से टाइप की गई सूची प्राप्त कर सकते हैं:

ResponseEntity<List<Rate>> rateResponse =
        restTemplate.exchange("https://bitpay.com/api/rates",
                    HttpMethod.GET, null, new ParameterizedTypeReference<List<Rate>>() {
            });
List<Rate> rates = rateResponse.getBody();

उपरोक्त अन्य समाधान भी काम करेंगे, लेकिन मुझे एक वस्तु [] के बजाय एक दृढ़ता से टाइप की गई सूची वापस प्राप्त करना पसंद है।


6
स्प्रिंग रन के साथ यह रन सुचारू रूप से 4.2.3 और - जैसा कि मैट ने कहा- ऑब्जेक्ट से बचने का बड़ा फायदा है []
मार्ज्ड

@ मैट - आप किस मार्शेलर को रेट ऑब्जेक्ट्स में जार को मार्शल करने के लिए उपयोग कर रहे हैं? मैं अनुमान लगा रहा हूँ कि यहाँ क्या हो रहा है, restTemplate.exchangeएक मार्शेलर के समय सभी जोंस मानों का मिलान मुख्य नामों के रूप में होता है जो कि रेट ऑब्जेक्ट में गुण होते हैं। आशा है कि मेरी विचार प्रक्रिया सही है।
निर्मल

बिल्कुल सही, स्प्रिंग बूट में ठीक काम करता है 1.4.0। कृपया धन्यवाद
आनंद

1
@ निर्मल वसंत मुझे विश्वास है कि डिफ़ॉल्ट रूप से जैक्सन का उपयोग करता है।
सोहैब

1
@SarvarNishonboev स्प्रिंगफ्रामवर्क.कोर से वर्तमान परिमाणितप्रकारप्रणाली अभी भी ठीक लगती है: docs.spring.io/spring-framework/docs/current/javadoc-api/org/…/
fspinnenhirn

75

मेरे लिए यह काम कर गया

Object[] forNow = template.getForObject("URL", Object[].class);
    searchList= Arrays.asList(forNow);

जहाँ ऑब्जेक्ट वह वर्ग है जो आप चाहते हैं


16
यह तब भी काम करता है जब आप एक क्लास का उपयोग करते हैं और न कि ऑब्जेक्ट की तरहCoupon[] coupons = restTemplate.getForObject( url, Coupon[].class)
lrkwz

1
यह एनपीई का कारण बन सकता है अगर HTTP प्रतिक्रिया शरीर खाली था (नहीं []बल्कि पूरी तरह से खाली)। इसलिए सावधान रहें और जांच करें null( if (forNow != null)...)।
रुस्लान Stelmachenko

1
मेरे गधे को बचाया :) आश्चर्य है कि जैक्सन द्वारा किस प्रकार का उपयोग किया जाता है, जब Object.classविधि में निर्दिष्ट किया जाता है getForObject()
एरिक वांग

5

कई परीक्षणों के बाद, यह सबसे अच्छा तरीका है जो मुझे मिला :)

Set<User> test = httpService.get(url).toResponseSet(User[].class);

आप सभी की जरूरत है

public <T> Set<T> toResponseSet(Class<T[]> setType) {
    HttpEntity<?> body = new HttpEntity<>(objectBody, headers);
    ResponseEntity<T[]> response = template.exchange(url, method, body, setType);
    return Sets.newHashSet(response.getBody());
}

नोट: इसके लिए अमरूद की आवश्यकता है
vphilipnyc

2

यहां मेरा बड़ा मुद्दा रेस्टटैम्पलेट को एक संगत कक्षा से मिलान करने के लिए आवश्यक वस्तु संरचना का निर्माण करना था। सौभाग्य से मुझे http://www.jsonschema2pojo.org/ मिला (एक ब्राउज़र में JSON प्रतिक्रिया प्राप्त करें और इसे इनपुट के रूप में उपयोग करें) और मैं इसे पर्याप्त नहीं सुझा सकता!


2

इससे पहले कि मैं अपनी परियोजनाओं में से किसी के लिए वास्तव में कुछ कार्यात्मक बंद कर दिया है और यहाँ है:

/**
 * @param url             is the URI address of the WebService
 * @param parameterObject the object where all parameters are passed.
 * @param returnType      the return type you are expecting. Exemple : someClass.class
 */

public static <T> T getObject(String url, Object parameterObject, Class<T> returnType) {
    try {
        ResponseEntity<T> res;
        ObjectMapper mapper = new ObjectMapper();
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
        ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setConnectTimeout(2000);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<T> entity = new HttpEntity<T>((T) parameterObject, headers);
        String json = mapper.writeValueAsString(restTemplate.exchange(url, org.springframework.http.HttpMethod.POST, entity, returnType).getBody());
        return new Gson().fromJson(json, returnType);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

/**
 * @param url             is the URI address of the WebService
 * @param parameterObject the object where all parameters are passed.
 * @param returnType      the type of the returned object. Must be an array. Exemple : someClass[].class
 */
public static <T> List<T> getListOfObjects(String url, Object parameterObject, Class<T[]> returnType) {
    try {
        ObjectMapper mapper = new ObjectMapper();
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
        restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
        ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setConnectTimeout(2000);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<T> entity = new HttpEntity<T>((T) parameterObject, headers);
        ResponseEntity<Object[]> results = restTemplate.exchange(url, org.springframework.http.HttpMethod.POST, entity, Object[].class);
        String json = mapper.writeValueAsString(results.getBody());
        T[] arr = new Gson().fromJson(json, returnType);
        return Arrays.asList(arr);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

मुझे उम्मीद है कि यह किसी की मदद करेगा!


1

यदि आप वस्तुओं की सूची पसंद करेंगे, तो ऐसा करने का एक तरीका इस प्रकार है:

public <T> List<T> getApi(final String path, final HttpMethod method) {     
    final RestTemplate restTemplate = new RestTemplate();
    final ResponseEntity<List<T>> response = restTemplate.exchange(
      path,
      method,
      null,
      new ParameterizedTypeReference<List<T>>(){});
    List<T> list = response.getBody();
    return list;
}

और इसका इस्तेमाल ऐसे करें:

 List<SomeObject> list = someService.getApi("http://localhost:8080/some/api",HttpMethod.GET);

उपरोक्त के लिए स्पष्टीकरण यहां पाया जा सकता है ( https://www.baeldung.com/spring-rest-template-list ) और नीचे लिखा है।

"उपरोक्त कोड में कुछ चीज़ें हो रही हैं। सबसे पहले, हम रिस्पोंसएंटिटी का उपयोग हमारे रिटर्न प्रकार के रूप में करते हैं, इसका उपयोग हम उन वस्तुओं की सूची को लपेटने के लिए करते हैं जिन्हें हम वास्तव में चाहते हैं। दूसरा, हम getForObject () के बजाय RestTemplate.exchange () कह रहे हैं। ।

RestTemplate का उपयोग करने का यह सबसे सामान्य तरीका है। इसके लिए हमें HTTP विधि, वैकल्पिक अनुरोध निकाय और एक प्रतिक्रिया प्रकार निर्दिष्ट करना होगा। इस मामले में, हम प्रतिक्रिया प्रकार के लिए ParameterizedTypeReference के एक अनाम उपवर्ग का उपयोग करते हैं।

यह अंतिम भाग वह है जो हमें JSON प्रतिक्रिया को उन वस्तुओं की सूची में बदलने की अनुमति देता है जो उपयुक्त प्रकार हैं। जब हम ParameterizedTypeReference का एक अनाम उपवर्ग बनाते हैं, तो यह उस प्रतिबिंब के उपयोग के लिए होता है जिस वर्ग के बारे में हम अपनी प्रतिक्रिया को बदलना चाहते हैं।

यह जावा के प्रकार ऑब्जेक्ट का उपयोग करके इस जानकारी को रखता है, और हमें अब प्रकार के क्षरण के बारे में चिंता करने की आवश्यकता नहीं है। "



1

आप प्रत्येक प्रविष्टि के लिए POJO बना सकते हैं जैसे,

class BitPay{
private String code;
private String name;
private double rate;
}

तो आप के रूप में उपयोग कर सकते हैं BitPay की सूची के ParameterizedTypeReference का उपयोग कर:

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<List<Employee>> response = restTemplate.exchange(
  "https://bitpay.com/api/rates",
  HttpMethod.GET,
  null,
  new ParameterizedTypeReference<List<BitPay>>(){});
List<Employee> employees = response.getBody();

-1

मुझे इस पोस्ट https://jira.spring.io/browse/SPR-8263 के आसपास काम मिला ।

इस पोस्ट के आधार पर आप इस प्रकार टाइप की गई सूची वापस कर सकते हैं:

ResponseEntity<? extends ArrayList<User>> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<User>>)ArrayList.class, userId);

4
यह काम नहीं करेगा, क्योंकि erasure के कारण किसी भी प्रकार की पैरामीटर जानकारी पास नहीं की जाती है getForEntity(Class<? extends ArrayList<User>>) ArrayList.classएक "असंगत प्रकार" संकलित त्रुटि भी देता है।
Esko Luontola
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.