web-dev-qa-db-fra.com

Obtenir la liste des objets JSON avec Spring RestTemplate

J'ai deux questions:

  • Comment mapper une liste d'objets JSON à l'aide de Spring RestTemplate.
  • Comment mapper des objets JSON imbriqués.

J'essaie de consommer https://bitpay.com/api/rates en suivant le didacticiel de http://spring.io/guides/gs/consuming-rest/ .

165
Karudi

Peut-être que de cette façon ...

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

Code du contrôleur pour la RequestMapping

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

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

ResponseEntity est une extension de HttpEntity qui ajoute un code d'état HttpStatus. Utilisé aussi dans RestTemplate méthodes @Controller . Dans RestTemplate cette classe est retournée par getForEntity() et exchange().

185
kamokaze

Commencez par définir un objet pour contenir l’entité revenant dans le tableau.

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

Ensuite, vous pouvez utiliser le service et obtenir une liste fortement typée via: 

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

Les autres solutions ci-dessus fonctionneront aussi, mais j'aime bien obtenir une liste fortement typée à la place d'un objet [].

273
Matt

Pour moi cela a fonctionné 

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

Où Object est la classe que vous voulez

66
yonia

Après plusieurs tests, c'est le meilleur moyen que j'ai trouvé :)

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

Tout ce dont vous avez besoin

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

Mon gros problème ici était de construire la structure Object requise pour faire correspondre RestTemplate à une classe compatible. Heureusement, j'ai trouvé http://www.jsonschema2pojo.org/ (obtenez la réponse JSON dans un navigateur et utilisez-la comme entrée) et je ne saurais trop le recommander!

2
upnorth

Envisagez cette réponse, en particulier si vous souhaitez utiliser des génériques dans ListSpring RestTemplate et des types génériques ParameterizedTypeReference, tels que List <T>

1
Moesio

j'ai déjà développé quelque chose de fonctionnel pour l'un de mes projets auparavant et voici le code:

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

J'espère que cela aidera quelqu'un!

1
Hamza Jeljeli

Si vous préférez une liste d'objets, une façon de le faire est la suivante:

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

Et utilisez-le comme suit:

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

Les explications concernant ce qui précède sont disponibles ici ( https://www.baeldung.com/spring-rest-template-list ) et sont paraphrasées ci-dessous.

"Il y a plusieurs choses qui se passent dans le code ci-dessus. Premièrement, nous utilisons ResponseEntity comme type de retour, que nous utilisons pour envelopper la liste des objets que nous voulons vraiment. Deuxièmement, nous appelons RestTemplate.exchange () au lieu de getForObject () .

C'est la manière la plus générique d'utiliser RestTemplate. Nous devons spécifier la méthode HTTP, le corps de la requête facultatif et un type de réponse. Dans ce cas, nous utilisons une sous-classe anonyme de ParameterizedTypeReference pour le type de réponse.

Cette dernière partie nous permet de convertir la réponse JSON en une liste d’objets de type approprié. Lorsque nous créons une sous-classe anonyme de ParameterizedTypeReference, il utilise la réflexion pour capturer des informations sur le type de classe vers lequel nous souhaitons convertir notre réponse.

Il conserve ces informations avec l’objet Type de Java et nous n’avons plus à nous soucier de l’effacement des types. "

0
Toofy

Vous pouvez créer un POJO pour chaque entrée comme,

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

puis en utilisant ParameterizedTypeReference of List of BitPay, vous pouvez utiliser comme:

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();
0
Nitin Pawar