You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit自定义反序列化器开发:响应信封封装处理需求

How to Build a Custom Retrofit Deserializer for Action-Specific Response Envelopes

Hey Tomislav, this is a super common pain point when working with APIs that wrap every response in a unique top-level envelope. Let’s break down how to create a reusable custom deserializer to handle this cleanly, without writing boilerplate for each endpoint.

Step 1: Define a Generic Envelope Class

First, notice all your responses share the same inner structure: ErrorCode, ErrorDescription, and Result—only the top-level key changes (like GetUserResult or GetPicturesResult). We can abstract this into a generic class to reuse the structure across all endpoints:

public class ApiEnvelope<T> {
    private int ErrorCode;
    private String ErrorDescription;
    private T Result;

    // Getters and setters (or use Lombok to skip writing these)
    public int getErrorCode() { return ErrorCode; }
    public void setErrorCode(int errorCode) { ErrorCode = errorCode; }
    public String getErrorDescription() { return ErrorDescription; }
    public void setErrorDescription(String errorDescription) { ErrorDescription = errorDescription; }
    public T getResult() { return Result; }
    public void setResult(T result) { Result = result; }
}

Step 2: Build the Custom JsonDeserializer

Next, we’ll write a deserializer that ignores the dynamic top-level key and parses the inner envelope into our generic ApiEnvelope class. Since each response only has one top-level key, we can safely grab the first entry in the JSON object:

import com.google.gson.*;
import java.lang.reflect.Type;

public class ApiEnvelopeDeserializer<T> implements JsonDeserializer<ApiEnvelope<T>> {
    @Override
    public ApiEnvelope<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // Extract the single top-level key (e.g., "GetUserResult") and its value
        JsonObject topLevelObject = json.getAsJsonObject();
        String topKey = topLevelObject.keySet().iterator().next();
        JsonElement envelopeContent = topLevelObject.get(topKey);

        // Let Gson handle parsing the inner envelope into our generic class
        return context.deserialize(envelopeContent, typeOfT);
    }
}

Step 3: Configure Gson and Retrofit

Now we need to tell Gson to use our custom deserializer for all ApiEnvelope instances, then wire this Gson setup into Retrofit:

// Create a Gson instance with our custom deserializer attached
Gson gson = new GsonBuilder()
        .registerTypeAdapter(ApiEnvelope.class, new ApiEnvelopeDeserializer<>())
        .create();

// Build your Retrofit client with this Gson converter
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("YOUR_API_BASE_URL")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

Step 4: Define Your Retrofit Interface

Finally, your API interface can return the generic ApiEnvelope with the actual data type you expect. No more worrying about the dynamic top-level key—Gson handles that under the hood:

public interface MyApiService {
    @POST("getUser")
    Call<ApiEnvelope<User>> getUser();

    @POST("getPictures")
    Call<ApiEnvelope<List<Picture>>> getPictures();

    @POST("getComment")
    Call<ApiEnvelope<Comment>> getComment();
}

Bonus: Simplify Error Handling (Optional)

If you want to avoid checking ErrorCode every time you make a call, you can add a helper method to extract the result or throw an error automatically:

public static <T> T getResultOrThrow(ApiEnvelope<T> envelope) throws ApiException {
    if (envelope.getErrorCode() != 0) {
        throw new ApiException(envelope.getErrorCode(), envelope.getErrorDescription());
    }
    return envelope.getResult();
}

Then use it in your callback to clean up the code:

myApiService.getUser().enqueue(new Callback<ApiEnvelope<User>>() {
    @Override
    public void onResponse(Call<ApiEnvelope<User>> call, Response<ApiEnvelope<User>> response) {
        if (response.isSuccessful()) {
            try {
                User user = getResultOrThrow(response.body());
                // Do something with the user data
            } catch (ApiException e) {
                // Handle API-specific errors (e.g., show error message)
            }
        }
    }

    @Override
    public void onFailure(Call<ApiEnvelope<User>> call, Throwable t) {
        // Handle network failures
    }
});

This approach keeps your code DRY and avoids repeating envelope-parsing logic for every endpoint.

内容的提问来源于stack exchange,提问作者Tomislav29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:20:09