如何在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
相关产品推荐
相关产品推荐

