Ottieni l'elenco di oggetti JSON con Spring RestTemplate


Risposte:


220

Forse in questo modo ...

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

Codice controller per il RequestMapping

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

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

ResponseEntityè un'estensione HttpEntityche aggiunge un HttpStatuscodice di stato. Utilizzato in RestTemplateoltre @Controllermetodi. In RestTemplatequesta classe viene restituito da getForEntity()e exchange().


Ha funzionato come un incantesimo, grazie. Forse mi puoi indirizzare ad altri tutorial o guide che potrei leggere su questo argomento?
Karudi,

2
meglio guardare qui su StackOverflow per alcuni frammenti di codice ed esempi o visitare il sito Web di primavera ufficiale ... TblGps [] a = responseEntity.getBody ();
Kamokaze,

È possibile farlo usando i generici? cioè il mio metodo ha un parametro Class <T estende Foo> e vorrei ottenere una raccolta di T dal metodo getForEntity.
Diskutant,

Sì, dovrebbe funzionare, ma potrebbe non essere pronto all'uso a seconda della versione spring / jackson e dei tipi di classe. Si tratta di serializzare / deserializzare i generici: lo stesso HTTP Request non si preoccupa di ciò che viene trasportato.
Kamokaze,


335

Definire innanzitutto un oggetto per trattenere l'entità che ritorna nell'array. Ad es

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

Quindi è possibile utilizzare il servizio e ottenere un elenco fortemente tipizzato tramite:

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

Anche le altre soluzioni sopra funzioneranno, ma mi piace recuperare un elenco fortemente tipizzato anziché un oggetto [].


6
Questa corsa si svolge senza problemi con Spring 4.2.3 e - come ha detto Matt - ha il grande vantaggio di evitare l'Oggetto []
Marged

@Matt - quale marshaller stai usando per portare il json in oggetti Rate? Immagino che sia quello che sta succedendo qui, al momento della restTemplate.exchangea marshallar mappa tutti i valori json con i nomi delle chiavi corrispondenti come proprietà nell'oggetto Rate. Spero che il mio processo di pensiero sia corretto.
Nirmal,

Perfetto, funziona benissimo in Spring Boot 1.4.0.RELEASE Grazie
Anand

1
@Nirmal Spring usa Jackson per impostazione predefinita, credo.
Sohaib,

1
@SarvarNishonboev l'attuale ParameterizedTypeReference di springframework.core sembra ancora a posto: docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
fspinnenhirn

75

Per me ha funzionato

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

Dove Object è la classe che desideri


16
Funziona anche se usi una classe e non un oggetto comeCoupon[] coupons = restTemplate.getForObject( url, Coupon[].class)
lrkwz il

1
Ciò può causare NPE se il corpo della risposta HTTP era vuoto (non []ma totalmente vuoto). Quindi fai attenzione e controlla null( if (forNow != null)...).
Ruslan Stelmachenko il

1
Mi sono salvato il culo :) Mi chiedevo che tipo fosse usato da Jackson, quando Object.classè specificato nel metodo getForObject().
Eric Wang,

5

Dopo più test, questo è il modo migliore che ho trovato :)

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

Tutto ciò che serve lì

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

Nota: questo richiede Guava
vphilipnyc il

2

Il mio grosso problema qui era quello di costruire la struttura degli oggetti richiesta per abbinare RestTemplate a una classe compatibile. Fortunatamente ho trovato http://www.jsonschema2pojo.org/ (ottenere la risposta JSON in un browser e usarla come input) e non posso raccomandarlo abbastanza!


2

in realtà ho sviluppato qualcosa di funzionale per uno dei miei progetti prima ed ecco il codice:

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

Spero che questo possa aiutare qualcuno!


1

Se preferisci un Elenco di oggetti, un modo per farlo è in questo modo:

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

E usalo così:

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

La spiegazione di quanto sopra è disponibile qui ( https://www.baeldung.com/spring-rest-template-list ) ed è parafrasata di seguito.

"Ci sono un paio di cose che accadono nel codice sopra. In primo luogo, utilizziamo ResponseEntity come nostro tipo di ritorno, usandolo per racchiudere l'elenco di oggetti che vogliamo davvero. In secondo luogo, stiamo chiamando RestTemplate.exchange () invece di getForObject () .

Questo è il modo più generico di usare RestTemplate. Ci richiede di specificare il metodo HTTP, il corpo della richiesta opzionale e un tipo di risposta. In questo caso, utilizziamo una sottoclasse anonima di ParameterizedTypeReference per il tipo di risposta.

Quest'ultima parte è ciò che ci consente di convertire la risposta JSON in un elenco di oggetti del tipo appropriato. Quando creiamo una sottoclasse anonima di ParameterizedTypeReference, utilizza la riflessione per acquisire informazioni sul tipo di classe in cui vogliamo convertire la nostra risposta.

Conserva queste informazioni utilizzando l'oggetto Type di Java e non dobbiamo più preoccuparci della cancellazione del tipo. "



1

Puoi creare POJO per ogni voce come,

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

quindi utilizzando ParameterizedTypeReference dell'elenco di BitPay è possibile utilizzare come:

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

Ho trovato lavoro in questo post https://jira.spring.io/browse/SPR-8263 .

Sulla base di questo post è possibile restituire un elenco digitato come questo:

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

4
Questo non funzionerà, perché a causa della cancellazione non vengono trasmesse informazioni sui parametri di tipo getForEntity. (Class<? extends ArrayList<User>>) ArrayList.classFornisce inoltre un errore di compilazione "tipi incompatibili".
Esko Luontola,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.