Spring RestTemplate ile JSON nesnelerinin listesini alma


199

İki sorum var:

  • Spring RestTemplate kullanarak bir JSON nesneleri listesi nasıl eşleştirilir.
  • İç içe JSON nesneleri nasıl eşlenir.

Http://spring.io/guides/gs/consuming-rest/ adresindeki öğreticiyi izleyerek https://bitpay.com/api/rates adresini kullanmaya çalışıyorum .


2
Özellikle genel liste kullanmak istiyorsanız bu yanıtı düşünün. Stackoverflow.com/questions/36915823/…
Moesio

Yanıtlar:


221

Belki bu taraftan ...

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

İçin denetleyici kodu RequestMapping

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

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

ResponseEntityHttpEntitybir HttpStatusdurum kodu ekleyen uzantıdır . Kullanılan RestTemplatesıra @Controlleryöntemlerle. Gelen RestTemplatebu sınıfı tarafından döndürülen getForEntity()ve exchange().


Bu bir cazibe gibi çalıştı, teşekkür ederim. Belki de beni bu konuda okuyabileceğim diğer derslere veya rehberlere yönlendirebilirsin?
Karudi

2
en iyi bazı kod parçacıkları ve örnekler için stackoverflow bakmak veya resmi bahar web sitesini ziyaret etmek ...... TblGps [] a = responseEntity.getBody ();
kamokaze

Jenerikler kullanarak bunu yapmak mümkün mü? yani benim yöntemi bir Class <T Foo> parametresini genişletir ve getForEntity yönteminden T bir koleksiyon almak istiyorum.
Diskutant

Evet, çalışmalıdır, ancak bahar / jackson sürümünüze ve sınıf türlerinize bağlı olarak kutunun dışında olmayabilir. Her şey jeneriklerin serileştirilmesi / serileştirilmesi ile ilgili - http İsteği kendisinin ne taşındığını umursamıyor.
kamokaze


337

Öncelikle diziye geri dönen objeyi tutmak için bir nesne tanımlayın.

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

Daha sonra hizmeti tüketebilir ve aşağıdakiler yoluyla güçlü bir şekilde yazılmış bir liste alabilirsiniz:

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

Yukarıdaki diğer çözümler de işe yarayacaktır, ancak Object [] yerine güçlü bir liste geri almak gibi.


6
Bu koşu Bahar 4.2.3 ile sorunsuz ve Matt'in dediği gibi
Nesneden

@Matt - json'u Rate nesnelerine marshal etmek için hangi marshaller'ı kullanıyorsunuz? Sanırım burada olan şey bu restTemplate.exchange, marshallar zamanında Rate nesnesindeki özellikler olarak eşleşen anahtar adlarına tüm json değerlerini eşler. Umarım düşünce sürecim doğrudur.
Nirmal

Mükemmel, Spring Boot 1.4.0'da iyi çalışıyor.GELDİR Teşekkürler
Anand

1
@Nirmal Spring varsayılan olarak Jackson kullanır inanıyorum.
Sohaib

1
@SarvarNishonboev şu anki ParameterizedTypeReference springframework.core adresinden gelen referans hala iyi görünüyor: docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
fspinnenhirn 26:19

75

Benim için bu işe yaradı

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

Nesne istediğiniz sınıftır


16
Object gibi bir sınıf kullanmasanız bile çalışırCoupon[] coupons = restTemplate.getForObject( url, Coupon[].class)
lrkwz

1
HTTP yanıt gövdesi boşsa ( []tamamen değil, tamamen boşsa) bu NPE'ye neden olabilir . Bu yüzden dikkatli olun ve null( if (forNow != null)...) öğesini kontrol edin .
Ruslan Stelmachenko

1
Kıçımı kurtardı :) Jackson tarafından ne tür merak edildiğini merak Object.class, yöntemde belirtildiğinde getForObject().
Eric Wang

5

Birden fazla testten sonra, bulduğum en iyi yol bu :)

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

Orada ihtiyacınız olan her şey

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());
}

Not: Bu Guava gerektirir
vphilipnyc

2

Buradaki en büyük sorunum RestTemplate'i uyumlu bir Sınıfla eşleştirmek için gereken Nesne yapısını oluşturmaktı. Neyse ki http://www.jsonschema2pojo.org/ buldum (bir tarayıcıda JSON yanıtı alın ve giriş olarak kullanın) ve bunu yeterince tavsiye edemez!


2

Aslında daha önce benim projelerden biri için fonksiyonel bir şey geliştirdi ve burada kod:

/**
 * @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;
    }
}

Umarım bu birisine yardım eder!


1

Bir Nesne Listesi tercih ederseniz, bunu yapmanın bir yolu şöyledir:

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

Ve şu şekilde kullanın:

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

Yukarıdakilere ilişkin açıklama burada bulunabilir ( https://www.baeldung.com/spring-rest-template-list ) ve aşağıda yorumlanmıştır.

"Yukarıdaki kodda birkaç şey oluyor. İlk olarak, gerçekten istediğimiz nesnelerin listesini sarmak için kullanarak ReturnEntity'yi dönüş türümüz olarak kullanıyoruz. İkincisi, getForObject () yerine RestTemplate.exchange () öğesini çağırıyoruz. .

RestTemplate'i kullanmanın en genel yolu budur. HTTP yöntemini, isteğe bağlı istek gövdesini ve bir yanıt türünü belirtmemizi gerektirir. Bu durumda, yanıt türü için anonim bir ParameterizedTypeReference alt sınıfı kullanırız.

Bu son bölüm, JSON yanıtını uygun türdeki nesneler listesine dönüştürmemize izin veren şeydir. ParameterizedTypeReference için anonim bir alt sınıf oluşturduğumuzda, yanıtımızı dönüştürmek istediğimiz sınıf türü hakkında bilgi yakalamak için yansıma kullanır.

Java'nın Type nesnesini kullanarak bu bilgileri saklıyor ve artık tür silme konusunda endişelenmemize gerek yok. "



1

Her giriş için POJO oluşturabilirsiniz,

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

daha sonra BitPay Listesinin ParameterizedTypeReference öğesini kullanarak şu şekilde kullanabilirsiniz:

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

Bu yazıdan https://jira.spring.io/browse/SPR-8263 adresinde iş buldum .

Bu gönderiye göre şöyle bir liste döndürebilirsiniz:

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

4
Bu çalışmaz, çünkü silme nedeniyle hiçbir tür parametre bilgisi iletilmez getForEntity. Ayrıca (Class<? extends ArrayList<User>>) ArrayList.class"uyumsuz türler" derleme hatası verir.
Esko Luontola
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.