如何使用kotlinx.serialization递归/增量解析45MB大型JSON文件
Android超大JSON解析内存优化方案
核心思路:流式解析,避免全量加载
不管用原生还是第三方库,核心都是不把整个JSON文件加载到内存,而是逐元素读取、处理、释放,这样内存占用能控制在几MB级别。
方案1:Android原生JsonReader(无依赖)
直接用Android SDK自带的JsonReader,从InputStream读取流,逐个解析JSON元素:
// 从文件获取InputStream,避免把整个文件读成String File jsonFile = new File(getFilesDir(), "large_data.json"); InputStream inputStream = new FileInputStream(jsonFile); JsonReader reader = new JsonReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); try { reader.beginArray(); // 假设根节点是数组,根据实际JSON结构调整 while (reader.hasNext()) { // 逐个解析单个对象,处理完立即释放 DataModel model = readSingleModel(reader); // 处理model:比如插入数据库、写入文件等,不要存到全局List中 processModel(model); } reader.endArray(); } finally { reader.close(); inputStream.close(); } // 解析单个对象的方法 private DataModel readSingleModel(JsonReader reader) throws IOException { DataModel model = new DataModel(); reader.beginObject(); while (reader.hasNext()) { String name = reader.nextName(); switch (name) { case "id": model.setId(reader.nextLong()); break; case "name": model.setName(reader.nextString()); break; // 其他字段按需解析 default: reader.skipValue(); // 跳过不需要的字段,节省内存 break; } } reader.endObject(); return model; }
方案2:Gson流式解析(适合用Gson的项目)
如果项目依赖Gson,同样用它的JsonReader做流式解析,不要用fromJson直接转成整个集合:
Gson gson = new Gson(); File jsonFile = new File(getFilesDir(), "large_data.json"); InputStream inputStream = new FileInputStream(jsonFile); JsonReader reader = new JsonReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); try { reader.beginArray(); while (reader.hasNext()) { // 逐个解析对象,处理后立即释放 DataModel model = gson.fromJson(reader, DataModel.class); processModel(model); } reader.endArray(); } finally { reader.close(); inputStream.close(); }
关键注意事项
- 绝对不要把JSON文件转成String再解析:比如用
FileUtils.readFileToString这类方法,会直接把45MB的文件加载到内存,加上Java String的UTF-16存储特性,内存占用会翻倍,再加上解析后的对象,直接触发OOM。 - 跳过不需要的字段:用
reader.skipValue()跳过无关字段,减少对象创建和内存占用。 - 及时释放资源:解析完立即关闭流,处理完的对象不要长期持有(比如不要加到全局集合,直接写入持久化存储)。
- 避免依赖largeHeap:在
AndroidManifest设置android:largeHeap="true"只是临时缓解,不同设备的largeHeap大小不一,还会掩盖内存问题,从解析方式优化才是根本。
为什么之前的方案失效?
大概率是因为方案仍在全量加载JSON(比如先转成String),或者没有真正用流式解析,而是一次性生成了整个对象集合,导致内存占用居高不下。
内容的提问来源于stack exchange,提问作者Bobby ESP
相关产品推荐
相关产品推荐

