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

Retrofit结合RxJava时Json序列化异常,RouteSchedule模型为空求助

Fixing Gson Mapping for Nested route-schedule Array with Retrofit & RxJava

Hey there! Let's work through this empty RouteSchedule model issue you're facing. The root problem here is almost certainly Gson not correctly locating the nested route-schedule array in your API response to map it to your model. Here are a few practical solutions to get your data loading properly:

1. Define an Outer Response Wrapper Class (Simplest Approach)

First, let's assume your API returns a structure like this (common for nested data):

{
  "meta": { /* some metadata */ },
  "route-schedule": [
    { "stop-id": "123", "arrival-time": "08:00", ... }
  ]
}

Your current Retrofit interface is probably trying to return Single<RouteSchedule> directly, but Gson can't skip the outer wrapper to reach the array. Instead, create a dedicated class to represent the full API response:

public class RouteScheduleApiResponse {
    // Use @SerializedName to match the exact key from the API (including hyphens)
    @SerializedName("route-schedule")
    private List<RouteSchedule> routeScheduleList;

    // Getter for the schedule list
    public List<RouteSchedule> getRouteScheduleList() {
        return routeScheduleList;
    }
}

Then update your Retrofit interface to return this wrapper class:

public interface TransitApi {
    @GET("your-endpoint")
    Single<RouteScheduleApiResponse> getRouteSchedule();
}

When you subscribe, you can extract the array directly from the wrapper:

transitApi.getRouteSchedule()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(response -> {
        List<RouteSchedule> schedules = response.getRouteScheduleList();
        // Use your schedule data here
    }, error -> {
        // Handle error
    });

2. Use a Custom Gson Deserializer (No Wrapper Class Needed)

If you don't want to add a wrapper class, you can create a custom deserializer to tell Gson exactly where to find the route-schedule array:

public class RouteScheduleDeserializer implements JsonDeserializer<List<RouteSchedule>> {
    @Override
    public List<RouteSchedule> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // Navigate to the nested "route-schedule" array in the response
        JsonObject rootObject = json.getAsJsonObject();
        JsonArray scheduleArray = rootObject.getAsJsonArray("route-schedule");
        
        // Let Gson handle mapping the array items to RouteSchedule objects
        return context.deserialize(scheduleArray, new TypeToken<List<RouteSchedule>>(){}.getType());
    }
}

Next, register this deserializer when building your Retrofit instance:

// Build Gson with the custom deserializer
Gson customGson = new GsonBuilder()
    .registerTypeAdapter(
        new TypeToken<List<RouteSchedule>>(){}.getType(),
        new RouteScheduleDeserializer()
    )
    .create();

// Create Retrofit with the custom Gson converter
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(YOUR_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create(customGson))
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build();

Now your Retrofit interface can return Single<List<RouteSchedule>> directly, and Gson will automatically extract the nested array:

public interface TransitApi {
    @GET("your-endpoint")
    Single<List<RouteSchedule>> getRouteSchedule();
}

3. Double-Check Your RouteSchedule Model Annotations

Don't overlook the basics! Make sure every field in your RouteSchedule class uses @SerializedName to match the exact key names from the API (especially those with hyphens, like stop-name or departure-time). Gson won't automatically map hyphenated keys to camelCase variable names unless you explicitly configure it:

public class RouteSchedule {
    @SerializedName("stop-id")
    private String stopId;
    
    @SerializedName("arrival-time")
    private String arrivalTime;
    
    // Add other fields with matching @SerializedName annotations
    // Getters and setters
}

If you have a lot of hyphenated keys, you can also configure Gson to handle this automatically:

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
    .create();

But using @SerializedName is more explicit and less error-prone if your API has mixed naming conventions.

Quick Debugging Tip

Add the HttpLoggingInterceptor to your Retrofit setup to print the raw API response. This will let you confirm that the route-schedule array actually exists in the response and matches the structure you're expecting:

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(logging)
    .build();

// Add this client to your Retrofit builder
Retrofit retrofit = new Retrofit.Builder()
    .client(client)
    // ... other configs
    .build();

Any of these approaches should fix the empty model issue. Start with the wrapper class if you want a straightforward solution, or use the custom deserializer if you prefer to keep your interface clean.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:07:03