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


199

2つの質問があります。

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

http://spring.io/guides/gs/sumption-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()


それは魅力のように働きました、ありがとう。多分あなたは私がこのトピックについて読むことができる他のいくつかのチュートリアルやガイドに私を導くことができますか?
Karudi、2014年

2
いくつかのコードスニペットと例については、ここでStackoverflowを参照するか、公式の春のWebサイトにアクセスするのが最善です...... TblGps [] a = responseEntity.getBody();
かもぜ2014年

ジェネリックを使用してこれを行うことは可能ですか?つまり、私のメソッドにはClass <T extends Foo>パラメーターがあり、getForEntityメソッドからTのコレクションを取得したいと考えています。
Diskutant 2015年

はい、動作するはずですが、Spring / Jacksonのバージョンとクラスのタイプによっては、すぐに使えるわけではありません。ジェネリックのシリアライズ/デシリアライズに関するすべて-HTTPリクエスト自体は、何が転送されるかを気にしません。
kamokaze 2015年


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

上記の他のソリューションも機能しますが、Object []ではなく、強く型付けされたリストを取得するのが好きです。


6
これは、実行者の円滑な春の4.2.3とと-マットが言ったように- ] [オブジェクトを回避する大きな利点を持っている
Marged

@Matt-jsonをRateオブジェクトにマーシャリングするためにどのマーシャラーを使用していますか?ここで何が起こっているのかと思います。restTemplate.exchangeマーシャラーがすべてのjson値を、Rateオブジェクトのプロパティとして一致するキー名にマッピングしているときです。私の思考プロセスが正しいことを願っています。
通常の2016年

パーフェクト、春ブーツ1.4.0.RELEASEのおかげで正常に動作します
アナンド

1
@Nirmal SpringはデフォルトでJacksonを使用していると思います。
Sohaib 2017年

1
:@SarvarNishonboev springframework.coreから現在ParameterizedTypeReferenceはまだ罰金だdocs.spring.io/spring-framework/docs/current/javadoc-api/org/...
fspinnenhirn

75

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

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

Objectは必要なクラスです。


16
これは、オブジェクトではなくクラスを使用しても機能しますCoupon[] coupons = restTemplate.getForObject( url, Coupon[].class)
lrkwz

1
これにより、HTTP応答の本文が空である([]完全に空ではない)場合、NPEが発生する可能性があります。したがって、注意してnullif (forNow != null)...)を確認してください。
Ruslan Stelmachenko 2017

1
私のお尻を保存しました:) Object.classメソッドで指定されているときに、ジャクソンでどのタイプが使用されているのか疑問に思いましたgetForObject()
Eric Wang

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

注:これにはGuavaが必要です
vphilipnyc

2

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


2

私は実際に以前に私のプロジェクトの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

オブジェクトのリストが必要な場合は、次のようにします。

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

次のようなエントリごとに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
消去のために型パラメーター情報がに渡されないため、これは機能しませんgetForEntity。また、(Class<? extends ArrayList<User>>) ArrayList.class「互換性のない型」コンパイルエラーを与えます。
Esko Luontola、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.