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

升级项目后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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:36:27