升级项目后Gson序列化android.location.Address返回空JSON字符串
解决Gson序列化新版
android.location.Address为空的问题 问题核心
升级Location库后,新版android.location.Address类的字段访问权限、命名或内部实现发生了变化,导致Gson默认的反射序列化机制无法读取字段值,最终输出空JSON字符串。
可行解决方案
方案1:自定义Gson TypeAdapter
手动编写TypeAdapter,通过反射或公共API提取需要的字段值,精准控制序列化逻辑:
public class AddressTypeAdapter extends TypeAdapter<Address> { @Override public void write(JsonWriter out, Address address) throws IOException { out.beginObject(); try { // 优先用公共get方法,避免依赖私有字段 out.name("latitude").value(address.getLatitude()); out.name("longitude").value(address.getLongitude()); out.name("countryName").value(address.getCountryName()); out.name("adminArea").value(address.getAdminArea()); out.name("locality").value(address.getLocality()); out.name("thoroughfare").value(address.getThoroughfare()); // 如果需要旧库中的私有字段,通过反射获取(注意字段名要匹配新版类) Field postalCodeField = Address.class.getDeclaredField("mPostalCode"); postalCodeField.setAccessible(true); out.name("postalCode").value((String) postalCodeField.get(address)); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } out.endObject(); } @Override public Address read(JsonReader in) throws IOException { // 不需要反序列化的话返回null即可 return null; } }
注册并使用该Adapter:
Gson gson = new GsonBuilder() .registerTypeAdapter(Address.class, new AddressTypeAdapter()) .create(); String json = gson.toJson(addressList);
方案2:封装适配DTO类
创建和旧库序列化结构一致的DTO类,将新版Address的数据拷贝进去后再序列化:
public class AddressDTO { public double latitude; public double longitude; public String countryName; public String adminArea; public String locality; // 其他需要和旧库保持一致的字段 public AddressDTO(Address address) { this.latitude = address.getLatitude(); this.longitude = address.getLongitude(); this.countryName = address.getCountryName(); this.adminArea = address.getAdminArea(); this.locality = address.getLocality(); // 其他字段一一映射 } }
转换后序列化:
List<AddressDTO> dtoList = new ArrayList<>(); for (Address addr : addressList) { dtoList.add(new AddressDTO(addr)); } String json = new Gson().toJson(dtoList);
方案3:配置Gson兼容私有字段
如果新版Address的字段只是改为私有但名称未变,可开启Gson访问私有字段的能力:
Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.STATIC) // 排除静态字段,按需调整 .create(); String json = gson.toJson(addressList);
注:如果新版类字段名和旧库不一致,需要配合@SerializedName注解映射字段名,但需确保能通过反射访问到私有字段。
关键注意点
- 优先使用Address类的公共get方法获取数据,避免直接依赖私有字段(私有字段可能在后续版本再次变更)。
- 测试时要对比新旧库序列化后的JSON结构,确保和原有适配逻辑兼容。
内容的提问来源于stack exchange,提问作者dartKnightRises
相关产品推荐
相关产品推荐

