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

如何在Android中使用Retrofit获取此类JSON响应的数据

在Android中使用Retrofit解析带动态键的JSON响应

嘿,这个Retrofit解析的问题我熟!你的JSON结构有点特别——外层是带动态数字键的位置数据,再加上一个status状态字段,咱们一步步来搞定它:

1. 先添加必要的依赖

首先在你的Module级build.gradle(或者build.gradle.kts)文件里,加入Retrofit核心库和Gson转换器的依赖——Gson帮我们把JSON自动转成Java/Kotlin对象:

dependencies {
    // Retrofit核心库,版本可以用最新稳定版
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // Gson转换器,用于JSON与实体类的互转
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

别忘了同步Gradle哦!

2. 定义对应的数据模型类

这个JSON的关键是那些动态的数字键("0"、"1"、"2"),咱们用Gson的@JsonAnySetter注解来处理这些不确定的键,同时定义两个数据类:

位置数据类(LocationData)

对应每个数字键里的具体内容,注意JSON里的"Long"是Java关键字,所以要用@SerializedName注解做字段映射:

import com.google.gson.annotations.SerializedName;

public class LocationData {
    private String userId;
    @SerializedName("Long") // 映射JSON中的"Long"字段
    private String longitude;
    @SerializedName("Lat")
    private String latitude;
    private String time;
    private String date;

    // 生成getter方法(如果用Lombok可以简化,手动写也没问题)
    public String getUserId() { return userId; }
    public String getLongitude() { return longitude; }
    public String getLatitude() { return latitude; }
    public String getTime() { return time; }
    public String getDate() { return date; }
}

外层响应类(ResponseData)

用@JsonAnySetter把所有动态数字键的内容存入Map,同时保留status字段:

import com.google.gson.annotations.JsonAnySetter;
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.Map;

public class ResponseData {
    @SerializedName("status")
    private String status;
    private Map<String, LocationData> locationEntries = new HashMap<>();

    // 这个注解会自动把所有未映射的字段(也就是"0","1","2")存入locationEntries
    @JsonAnySetter
    public void setLocationEntry(String key, LocationData value) {
        locationEntries.put(key, value);
    }

    // getter方法
    public String getStatus() { return status; }
    public Map<String, LocationData> getLocationEntries() { return locationEntries; }
}

如果是用Kotlin开发,数据类会更简洁,思路和Java版本完全一致~

3. 创建Retrofit请求接口

定义一个接口,声明你的API请求方法,假设是GET请求:

import retrofit2.Call;
import retrofit2.http.GET;

public interface LocationApi {
    // 替换成你实际的API端点路径
    @GET("your-location-api-path")
    Call<ResponseData> fetchLocationData();
}

4. 初始化Retrofit并发起请求

在你的Activity、ViewModel或者Repository里,初始化Retrofit实例,发起请求并处理响应:

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

// 初始化Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://your-api-base-url.com/") // 替换成你的API基础URL
        .addConverterFactory(GsonConverterFactory.create())
        .build();

// 创建接口实例
LocationApi locationApi = retrofit.create(LocationApi.class);

// 发起异步请求(推荐用异步,避免阻塞主线程)
Call<ResponseData> call = locationApi.fetchLocationData();
call.enqueue(new Callback<ResponseData>() {
    @Override
    public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
        if (response.isSuccessful() && response.body() != null) {
            ResponseData responseData = response.body();
            // 先检查状态是否成功
            if ("success".equals(responseData.getStatus())) {
                // 获取所有位置数据
                Map<String, LocationData> locationMap = responseData.getLocationEntries();
                // 遍历Map处理每个位置项
                for (Map.Entry<String, LocationData> entry : locationMap.entrySet()) {
                    String key = entry.getKey(); // 就是"0","1","2"这些标识
                    LocationData location = entry.getValue();
                    // 这里可以把数据展示到UI,或者做其他处理
                    System.out.println("Key: " + key + " | UserId: " + location.getUserId() + " | 经度: " + location.getLongitude());
                }
            } else {
                System.out.println("接口返回状态失败");
            }
        } else {
            System.out.println("请求成功但响应异常: " + response.message());
        }
    }

    @Override
    public void onFailure(Call<ResponseData> call, Throwable t) {
        // 请求失败,处理错误(比如网络问题)
        System.out.println("请求失败: " + t.getMessage());
    }
});

最后几个小提醒

  • 别忘了在AndroidManifest.xml里添加网络权限:<uses-permission android:name="android.permission.INTERNET" />
  • 如果你的经纬度是数值类型(不是字符串),可以把LocationData里的longitude和latitude改成Double类型,Gson会自动转换
  • 推荐把网络请求放到ViewModel或者Repository里,不要直接写在Activity里,符合MVVM架构规范

内容的提问来源于stack exchange,提问作者Nitish Kumar Tiwary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:07:08