web-dev-qa-db-ja.com

Spring RestTemplateを使ってJSONオブジェクトのリストを取得する

2つ質問があります。

  • Spring RestTemplateを使用してJSONオブジェクトのリストをマップする方法。
  • 入れ子になったJSONオブジェクトをマップする方法。

http://spring.io/guides/gs/consuming-rest/ からチュートリアルに従うことによって、 https://bitpay.com/api/rates を消費しようとしています。

170
Karudi

たぶんこのように...

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()によって返されます。

192
kamokaze

まず、配列に戻ってくるエンティティを保持するためのオブジェクトを定義します。

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

上記の他の解決策でもうまくいくでしょうが、Object []の代わりに強く型付けされたリストを返すのが好きです。

281
Matt

私にとってこれはうまくいった

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

Objectが必要なクラスです。

66
yonia

複数のテストの後、これが私が見つけた最良の方法です:)

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

ここでの私の大きな問題は、RestTemplateを互換クラスに一致させるのに必要なオブジェクト構造を構築することでした。幸いなことに、 http://www.jsonschema2pojo.org/ (ブラウザでJSONレスポンスを取得し、それを入力として使用する)が見つかりましたが、これは十分お勧めできません。

2
upnorth
1
Moesio

私は実際に前に私のプロジェクトの1つのために機能的な何かを開発しました、そしてここにコードがあります:

/**
 * @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
Hamza Jeljeli

オブジェクトのリストを好むのであれば、それを行う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 )にあり、以下に言い換えます。

「上のコードでは、いくつかのことが起こります。まず、ResponseEntityを戻り型として使用し、それを使用して、必要なオブジェクトのリストをラップします。次に、getForObject()ではなくRestTemplate.exchange()を呼び出します。 。

これがRestTemplateを使用する最も一般的な方法です。 HTTPメソッド、オプションのリクエストボディ、そしてレスポンスタイプを指定する必要があります。この場合、レスポンスタイプにはParameterizedTypeReferenceの無名サブクラスを使用します。

この最後の部分で、JSONレスポンスを適切なタイプのオブジェクトのリストに変換できます。 ParameterizedTypeReferenceの匿名サブクラスを作成すると、リフレクションを使用してレスポンスの変換先となるクラスタイプに関する情報を取得します。

JavaのTypeオブジェクトを使用してこの情報を保持しており、型の消去について心配する必要はもうありません。」

1
Toofy

以下のように、各エントリに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();
0
Nitin Pawar