4.Json实践项目总结

4.总结


4.1 知识点

实践小项目做了什么

问题抛出

问题解决


4.2 核心要点速览

项目在做什么

业务脚本只面对一个入口:JsonDataMgr.Instance。它把「对象 ↔ Json 文本 ↔ 磁盘文件」三件事收进管理器:对外是保存任意 object、按文件名加载成 T,内部再决定落盘路径和用哪套序列化 API。

本课要落地的能力:单例管理器;JsonTypeJsonUtility 与 LitJson 之间切换;SaveData / LoadData 的默认方案与课内代码一致,默认走 LitJson。

路径策略:为什么读要「先包内、再本地」,写只往 persistent

  • SaveData:路径固定为 Application.persistentDataPath + "/" + fileName + ".json"。这是运行时可写目录,适合存档、下载配置、玩家改过的表。
  • LoadData:先拼 Application.streamingAssetsPath 下的同名文件;不存在再换 Application.persistentDataPath。典型用法是 StreamingAssets 里放随包发布的默认 Json,persistent 里放 覆盖版或用户存档;先读包内底稿,没有再落到用户目录。
  • 都没有:直接 return new T(),所以泛型必须 where T : new(),否则无法在无文件时安全构造默认对象。
步骤 目录根 用途直觉
保存 persistentDataPath 需要写入、可覆盖的文件
读取优先 streamingAssetsPath 只读、随包资源
读取回退 persistentDataPath 本地生成或已修改的副本

JsonType 与分支里的 API

switch (type) 里两套调用必须成对使用;存的时候用 LitJson、读的时候误选 JsonUtility,很容易得到空字段或解析异常。

JsonType 序列化 反序列化
JsonUtility JsonUtility.ToJson JsonUtility.FromJson<T>
LitJson JsonMapper.ToJson JsonMapper.ToObject<T>

课里默认参数是 JsonType.LitJson,因此工程里必须带 LitJson 源码或引用,导出包时也要一并勾选,否则别的项目导入后会缺类型。

管理器最小骨架

public class JsonDataMgr
{
    private static JsonDataMgr instance = new JsonDataMgr();
    public static JsonDataMgr Instance => instance;
    private JsonDataMgr() { }
    // SaveData / LoadData:见系列正文完整实现
}

私有构造拦住 new JsonDataMgr(),只保留 Instance 单入口,避免场景里挂多个管理器各写各的文件。


4.3 面试题精选

进阶题

1. 保存和读取为什么用不同的路径策略

题目

SaveData 为什么只往 Application.persistentDataPath 写,而 LoadData 要先查 Application.streamingAssetsPath 再回退到 persistent?

深入解析
  • :StreamingAssets 在多数平台是只读或不适合运行时改写;持久化存档、玩家配置必须落在可写目录,persistent 是 Unity 提供的跨平台可写沙箱路径。
  • :包内默认数据随安装走,适合放 StreamingAssets;用户下载补丁、本地改键位、存档则落在 persistent。先读包内再读本地,等于「默认表 + 用户覆盖」的常见组合。
  • 面试收口:一句话说清「写要可写、读要先只读后可写」,再各举一个游戏里的例子即可。
答题示例

保存必须写到运行时允许改写的目录,所以课里用 persistentDataPath。

读取先找 StreamingAssets,一般是随包的默认 Json;没有再用 persistent,对应存档或本地覆盖。这样发布默认配置和玩家数据能分到两个目录里。

参考文章
  • 2.Json数据管理类存储和读取数据

2. JsonType 枚举解决了什么问题

题目

为什么要单独做 JsonType 枚举,并把默认方案设为 LitJson?

深入解析
  • 工程意义:同一套业务接口下可以切换序列化实现,方便对比、迁移或按平台选实现,而不是把 JsonUtility / JsonMapper 写死在调用点。
  • 默认 LitJson:课内管理器代码默认走 LitJson 分支,与项目里引入的 LitJson 源码一致;若默认改成 JsonUtility 却未改依赖,会造成「代码默认」和「工程引用」错位。
  • 注意点:存和读必须选同一种 JsonType,否则格式细节不一致会直接反序列化失败。
答题示例

枚举把「用哪套库」变成显式参数,Save 和 Load 可以统一切换。

默认 LitJson 是因为项目里集成了 LitJson,管理器示例按这个依赖来写;真正项目里默认值要跟包内引用一致,而且读写要用同一个枚举值。

参考文章
  • 2.Json数据管理类存储和读取数据

3. 泛型约束与无文件时的返回值

题目

LoadData<T> 为什么要写 where T : new()?和「文件不存在就 return new T()」是什么关系?

深入解析
  • 编译期new T() 要求编译器知道 T 有无参构造;where T : new() 是 C# 对该写法的约束。
  • 语义:无文件时返回「默认空对象」而不是 null,调用方可以少写一层 null 判断,但要清楚空对象和「有文件但字段全默认」在数据上可能无法区分
  • 延伸:若类型只有带参构造或单例,不能直接套这个写法,需要改工厂或默认值策略。
答题示例

new T() 要求 T 能无参构造,所以要加 where T : new()

找不到文件时返回 new T(),相当于给调用方一个「空档」而不是 null,用起来简单;但要心里有数,这和「读了文件但内容全是默认值」可能长得一样。

参考文章
  • 2.Json数据管理类存储和读取数据

4. 导出包为什么要带上 LitJson

题目

生成 unitypackage 给别的工程用时,为什么要强调把 LitJson 文件夹一起导出?

深入解析
  • 依赖关系JsonMapper 等类型来自 LitJson,不把源码或程序集打进包,导入方会大量编译错误。
  • 操作层面:在导出树里勾选整个 LitJson 目录,并善用「包括依赖项」,避免只勾了 JsonDataMgr.cs 漏掉库。
  • 对比:若项目只用 JsonUtility,则不必带 LitJson;一旦默认分支是 LitJson,包内容必须与之一致。
答题示例

管理器默认用 LitJson 的 API,LitJson 是外部脚本库,不导出的话别的工程没有 JsonMapper 这些类。

所以导出时要勾选整个 LitJson 目录,最好开包括依赖项,和课里截图一致。

参考文章
  • 3.生成资源包

深度题

1. 同名 Json 在两处都存在时读哪一份

题目

fileName.json 同时存在于 streamingAssetsPathpersistentDataPath,当前课内 LoadData 会读哪一边?这种优先级适合什么业务?

深入解析
  • 代码路径:先赋值 StreamingAssets 全路径,File.Exists 为真则不会再切到 persistent,因此永远读包内那份
  • 业务含义:适合「包内是只读母版,只有包内没有该文件时才用本地生成的」;若期望「本地永远覆盖包内」,课内逻辑需要改成先查 persistent 或合并策略,而不是照抄当前顺序。
  • 踩坑:策划若以为改 persistent 里文件能覆盖包内同名表,在当前实现下不会生效
答题示例

会先检查 StreamingAssets,存在就直接读,不会读到 persistent。

适合包内带默认配置、本地只在「没有包内文件」时才生效的场景。如果要玩家覆盖版一定优先,就要调整判断顺序或加版本号分流。

参考文章
  • 2.Json数据管理类存储和读取数据

2. 同步读写 API 的边界

题目

课里用 File.WriteAllTextFile.ReadAllText 一次性读完、写完整个 Json 文件。在什么情况下这可能成为问题?可以怎么演进?

深入解析
  • 主线程阻塞:文件较大或移动设备存储慢时,同步 IO 可能造成明显卡顿或掉帧;Unity 主线程做重 IO 是常见性能雷点。
  • 内存峰值ReadAllText 一次性把字符串载入内存,超大表会拉高峰值。
  • 演进方向:拆分为异步 API、分帧加载、或边读边解析的流式方案;存档类小文件通常仍可接受同步写法。
  • 答题边界:不必展开所有平台差异,点到「主线程 + 大文件」即可。
答题示例

同步读写会在主线程上等磁盘,文件大或设备慢时会卡帧。

小存档一般没问题;配置表很大时可以考虑异步、分块读或流式解析。WriteAllText、ReadAllText 适合课里先把逻辑讲清楚,上线要按体量评估。

参考文章
  • 2.Json数据管理类存储和读取数据


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏