【问题标题】:gson.toJson giving "[{}]" after migrating to API 31 Android 12gson.toJson 在迁移到 API 31 Android 12 后给出“[{}]”
【发布时间】:2022-12-14 05:48:44
【问题描述】:

将 targetSdk 更新为 31 后,gson.ToJson 开始在 android 12 设备 (vivo v2036) 上为 List<File> 提供空结果。尝试传递 TypeToken 仍然保持不变。有趣的是,它在低端机器人和 targetSdk 30 上运行良好。

public void save(Context context, List<File> files) {
    Gson gson = new Gson();
    String json = gson.toJson(files);
    //getting json value as "[{}]"
}

【问题讨论】:

  • 将您的 List&lt;File&gt; 转换为 List&lt;String&gt; 并将其序列化。

标签: java android gson android-12 target-sdk


【解决方案1】:

Gson 没有针对 java.io.File 的内置适配器,因此它会回退到使用反射。第三方类应该避免这种情况,因为它会访问它们的内部字段,这使您依赖于它们的内部实现。该内部实现可能随时更改,因为它不是公共 API 的一部分,因此可能会破坏您的 JSON 序列化逻辑。

作为mentioned by @CommonsWare,您可以将列表的类型更改为List&lt;String&gt;,这样做只使用 Gson 具有内置适配器的类型。或者你也可以通过为File注册一个自定义的TypeAdapter来解决这个问题:

class FileTypeAdapter extends TypeAdapter<File> {
    @Override
    public void write(JsonWriter out, File file) throws IOException {
        if (value == null) {
            out.nullValue();
        } else {
            out.value(file.getPath());
        }
    }

    @Override
    public File read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        } else {
            return new File(in.nextString());
        }
    }
}

(巧合的是,这个自定义的 TypeAdapter 也会生成更紧凑的 JSON,因为它将 File 序列化为 JSON 字符串值,而基于反射的适配器会将其序列化为具有 JSON 字符串属性的 JSON 对象。)

然后您可以像这样注册适配器:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(File.class, new FileTypeAdapter())
    .create();

如果这不能解决您的问题,您也可以尝试使用GsonBuilder.registerTypeHierarchyAdapter 注册适配器。可能 Android 正在创建自定义 File 子类的实例。

要检测您不小心依赖于 Android 类的基于反射的序列化的任何情况,您可以使用 GsonBuilder.addReflectionAccessFilter​(ReflectionAccessFilter.BLOCK_ALL_ANDROID)(需要 Gson 2.9.1 或更新版本)。

【讨论】:

    猜你喜欢
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 2022-11-18
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多