Retrofit 2에서 빈 응답 본문을 어떻게 처리 할 수 ​​있습니까?


125

최근에 Retrofit 2를 사용하기 시작했고 빈 응답 본문을 구문 분석하는 문제에 직면했습니다. 응답 본문 내부에 내용이없는 http 코드로만 응답하는 서버가 있습니다.

서버 응답 (헤더, 상태 코드 등)에 대한 메타 정보 만 처리하려면 어떻게해야합니까?

답변:


216

편집하다:

Jake Wharton이 지적했듯이

@GET("/path/to/get")
Call<Void> getMyData(/* your args here */);

내 원래 응답에 비해 가장 좋은 방법입니다.

을 반환 ResponseBody하면 응답 구문 분석을 우회 할 수 있습니다 .

@GET("/path/to/get")
Call<ResponseBody> getMyData(/* your args here */);

그런 다음 전화로

Call<ResponseBody> dataCall = myApi.getMyData();
dataCall.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Response<ResponseBody> response) {
        // use response.code, response.headers, etc.
    }

    @Override
    public void onFailure(Throwable t) {
        // handle failure
    }
});

58
더 나은 : Void더 나은 의미를 가질뿐만 아니라 빈 케이스에서 (약간) 더 효율적이고 비어 있지 않은 케이스에서 훨씬 더 효율적입니다 (몸에 관심이 없을 때).
Jake Wharton 2015 년

1
@JakeWharton 대단한 행동입니다. 지적 해 주셔서 감사합니다. 답변이 업데이트되었습니다.
iagreen

2
좋은 대답입니다. Void를 사용하지 않는 한 가지 이유는 요청이 실패 할 때만 본문을 반환하는 리소스가 있고 errorBody ResponseBody를 특정 또는 일반적인 유형으로 변환하려는 경우입니다.

7
@JakeWharton 사용하기 좋은 제안 Void. 사용겠습니까 Unit코 틀린 코드는 동일한 혜택을 제공 Void개조를위한 자바를?
Akshay Chordiya

6
@ akshay-chordiya 방금 확인한 UnitKotlin에서 작동 Void하지 않지만 작동 합니다. 어딘가에 하드 코딩 된 수표가 있다고 가정합니다.
user3363866

40

RxJava를 사용 Completable하는 경우이 경우 에 사용하는 것이 좋습니다.

값없이 지연된 계산을 나타내지 만 완료 또는 예외에 대한 표시 만 나타냅니다. 이 클래스는 Reactive-Streams와 유사한 이벤트 패턴을 따릅니다. onSubscribe (onError | onComplete)?

http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Completable.html

받아 들여진 대답에서 :

@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);

엔드 포인트가 실패 응답 코드를 반환하는 경우에도 여전히에 있으며 onNext응답 코드를 직접 확인해야합니다.

그러나 Completable.

@GET("/path/to/get")
Completable getMyData(/* your args here */);

당신은 단지 것 onComplete하고 onError. 응답 코드가 성공하면 onComplete다른 코드가 실행됩니다 onError.


1
이 경우 onError Throwable논쟁에는 무엇이 포함됩니까? 나는 이것이 더 깨끗하다고 ​​생각하지만 우리는 종종 실패에 대한 응답 코드와 본문을 살펴 봐야합니다.
big_m

24

rxjava를 사용하는 경우 다음과 같이 사용하십시오.

@GET("/path/to/get")
Observable<Response<Void>> getMyData(/* your args here */);

그것이 내가 찾은 것입니다! 감사!
Sirelon

PUT REST 요청을 위해 RxJava2 및 Retrofit2와 함께 ResposeBody를 사용했습니다. 그것은 잘 작동
모티 Bartov

1
성공하면 빈 본문을 반환하고 오류가 발생하면 json 본문을 반환하는 엔드 포인트 API가 있습니다. Response <Void>를 사용하는 경우 오류 사례를 어떻게 처리 할 수 ​​있습니까?
KeNVin Favo

여기서 사용하는 응답 클래스는 무엇입니까? 개조 또는 OKHttps?
Matthias

1
예외에 대한 오류 처리를 수행하는 경우 좋은 옵션이 아닙니다.이 접근 방식에서는 예외가 발생하지 않지만 오류에 대한 응답으로 JSON이 발생합니다
Ovi Trif

0

다음은 PUT REST 요청과 함께 Rx2 및 Retrofit2와 함께 사용한 방법입니다. 내 요청에는 json 본문이 있지만 본문이 비어있는 http 응답 코드 만 있습니다.

Api 클라이언트 :

public class ApiClient {
public static final String TAG = ApiClient.class.getSimpleName();


private DevicesEndpoint apiEndpointInterface;

public DevicesEndpoint getApiService() {


    Gson gson = new GsonBuilder()
            .setLenient()
            .create();


    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    okHttpClientBuilder.addInterceptor(logging);

    OkHttpClient okHttpClient = okHttpClientBuilder.build();

    apiEndpointInterface = new Retrofit.Builder()
            .baseUrl(ApiContract.DEVICES_REST_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
            .create(DevicesEndpoint.class);

    return apiEndpointInterface;

}

인터페이스 :

public interface DevicesEndpoint {
 @Headers("Content-Type: application/json")
 @PUT(ApiContract.DEVICES_ENDPOINT)
 Observable<ResponseBody> sendDeviceDetails(@Body Device device);
}

그런 다음 사용하려면 :

    private void sendDeviceId(Device device){

    ApiClient client = new ApiClient();
    DevicesEndpoint apiService = client.getApiService();
    Observable<ResponseBody> call = apiService.sendDeviceDetails(device);

    Log.i(TAG, "sendDeviceId: about to send device ID");
    call.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<ResponseBody>() {
        @Override
        public void onSubscribe(Disposable disposable) {
        }

        @Override
        public void onNext(ResponseBody body) {
            Log.i(TAG, "onNext");
        }

        @Override
        public void onError(Throwable t) {
            Log.e(TAG, "onError: ", t);

        }

        @Override
        public void onComplete() {
            Log.i(TAG, "onCompleted: sent device ID done");
        }
    });

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.