7.Json基础知识总结

7.总结


1.1 知识点

总结主要内容

学习内容回顾

优点

缺点

主要用处

实践预告


7.2 核心要点速览

Json 语法与对象结构

  • 整体形态{} 表示一个对象(一组键值对),[] 表示数组;可嵌套,数组里常放多个同结构对象表示列表。
  • 键的写法:键必须是双引号字符串;单引号、无引号不符合标准 Json,解析器通常会拒收。
  • 值的类型:数字、true / falsenull、双引号字符串、对象、数组;与 C# 字段常见对应是:嵌套类/结构 ↔ 内层 {},集合或数组字段 ↔ []
  • null:可选子结构可写 null(如无武器时 weaponnull),代码侧要对可空与默认值有统一约定。
  • 字典与键类型:对象即「字符串键 → 值」;C# 用整数键的字典落到 Json 里键仍会写成 "1""2" 这种字符串,反序列化时别假定键还是数值类型。
  • 注释与落盘:标准 Json 不含 //、块注释;用 jsonc 写草稿可以,交给 JsonUtility 等前必须删注释,否则解析失败。

Excel 表转 Json 工作流

  • 目的:表驱动配置,策划维护 Excel,程序读导出的 Json。
  • 课堂步骤:Excel 排好列 → 复制 → 网页转换工具粘贴 → 得到文本 → 粘进项目 .json 保存。
  • 转换后必查:工具可能搞错类型(数字变字符串)、合并单元格、空行、精度等;合入工程前要复查
  • 常见顶层结构:多行配表常是对象数组 [{...},{...}],一行一条逻辑记录。
  • 工程化:长期应用脚本、编辑器拓展或构建步骤一键导出,减少手工复制(正文已预告后续方向)。

读取Json文件方法

  • File.WriteAllText:整文件写入字符串;父目录须已存在,否则抛异常(不会自动建多级目录)。
  • File.ReadAllText:整文件读出为字符串,再交给 JsonUtilityLitJson
  • 路径习惯:可写存档常用 Application.persistentDataPath;只读配表可用 StreamingAssets(注意部分平台只读与加载方式差异)。
操作 关键类/方法 代码示例 说明
写文件 File.WriteAllText File.WriteAllText(Application.persistentDataPath + "/Test.json", "存储内容"); 先确保目录存在
读文件 File.ReadAllText string str = File.ReadAllText(Application.persistentDataPath + "/Test.json"); 注意编码为 UTF-8

JsonUtility

  • Unity 内置:JsonUtility.ToJsonJsonUtility.FromJson(字符串, typeof(T))JsonUtility.FromJson<T>(字符串)
  • 特性:参与序列化的类型加 [System.Serializable];私有、受保护成员要进 Json 需 [SerializeField]
  • 字典:不支持;这类字段不会按字典语义出现在 Json 里(正文示例中字典字段被跳过)。
  • null 子对象ToJson 时引用为 null 常被写成默认空结构(如 "s1":{"age":0,"name":""}),与标准「就是 null」的直觉不一致。
  • float:可能出现小数打印误差。
  • 反序列化容错:Json 少写字段不报错,成员保持默认值。
  • 根节点:Json 顶层必须是对象 {};配表是 [{...}] 时不能 FromJson<List<T>>,要壳类如 class RoleData { public List<RoleInfo> list; },Json 里用字段包住数组。
  • 编码:文件须 UTF-8
操作 API 示例
序列化 ToJson string s = JsonUtility.ToJson(obj);
反序列化 FromJson<T> var t = JsonUtility.FromJson<MrTao>(jsonStr);

LitJson

  • 第三方:将源码目录拷入工程,using LitJson;,用 JsonMapper 静态方法。
  • 序列化 / 反序列化JsonMapper.ToJson(obj);强类型用 JsonMapper.ToObject<T>(jsonStr);弱类型可先 JsonData data = JsonMapper.ToObject(jsonStr),再 data["name"] 取值。
  • 类型规则:不要求 [Serializable]只序列化 public 字段;自定义类型要提供 无参构造函数,否则 ToObject<T> 失败。
  • 字典:键用 string 最稳;Json 键全是带引号的字符串,数值键在文本里也是 "1" 这种形式。
  • 集合:可直接 JsonMapper.ToObject<RoleInfo[]>(jsonStr)ToObject<List<RoleInfo>>(jsonStr),贴合 Excel 导出的对象数组。
  • null:能较直接地保留 null 语义。
  • 易错点:工具生成的文本可能在最后一元素后多逗号,整段变非法 Json;编码同样要 UTF-8

JsonUtility 与 LitJson 对照

JsonUtility LitJson
来源 Unity 内置 拷贝源码进项目,占维护成本
特性 Serializable / SerializeField 不要
私有字段 SerializeField 可序列化 不参与
字典 不支持 支持,键用 string
顶层数组 / List 须壳类包一层 可直接 ToObject<List<T>>
null 常落成默认空数据 可写 null
无参构造 不强制 自定义类型必须有

选型提示

  • 结构简单、不想引第三方、只有「对象套数组」且愿意写壳类,JsonUtility 足够。
  • 配表根是数组、要字典、少写特性、null 要准确,正文更常推荐 LitJson;仍要评估源码版本与项目规范。

7.3 面试题精选

基础题

1. 数据持久化到底在解决什么问题

题目

请说明什么是数据持久化,并举例说明「持久化数据」和「仅存在内存中的数据」在程序退出后有什么不同表现。

深入解析
  • 持久化:把需要跨运行周期保留的信息写入磁盘、云端存档等介质,下次启动还能读回来。
  • 内存数据:随进程销毁而丢失,除非在退出前主动写回持久层。
  • 游戏向例子:玩家金币如果只放在运行时的静态变量里,关游戏就没了;写入存档文件或服务器后才算持久化。
答题示例

持久化是让数据在程序关掉之后还在,比如写到本地文件或服务器。

只放在内存里的变量,进程一结束就没了;要保留进度、设置、背包等,必须在合适的时机序列化并落盘或上传。

参考文章
  • 1.概述

2. 文件后缀名对实际开发有什么意义

题目

文件名后缀(扩展名)能告诉我们什么?为什么不能仅凭后缀断定文件内容一定正确?

深入解析
  • 意义:约定俗成的类型提示,方便系统关联默认程序、团队沟通时一眼知道「大概是配置、贴图还是表格导出」。
  • 局限:后缀可以随意改,内容可能是错的编码、截断的文件或根本不是该格式;真正可靠的是打开后按格式规范解析、必要时做校验。
  • 和 Json 的关系.json 只说明「通常按 Json 文本规范去读」,仍要处理非法 Json、编码错误等问题。
答题示例

后缀主要是类型提示,方便识别和关联工具,比如 .json 一般当文本结构化数据打开。

但不能迷信后缀,内容对不对要靠解析和校验;后缀改个名并不能改变文件真实格式。

参考文章
  • 1.概述

3. Json 里键名为什么必须用双引号

题目

标准 Json 中对象的键能否用单引号或不写引号?为什么?

深入解析
  • 规范要求键是 JSON String,即双引号包裹、内部按转义规则处理。
  • 单引号、裸标识符属于 JavaScript 对象字面量习惯,不是标准 Json;JsonUtility、多数服务端解析器会判非法。
  • 面试加分:提到 RFC 8259 或「与 JS 字面量区分」即可,不必展开所有转义细节。
答题示例

标准 Json 的键必须是双引号字符串。

单引号或不加引号是 JavaScript 写法,很多严格解析器不认;Unity 里用 JsonUtility 也会按标准 Json 来解析。

参考文章
  • 2.Json文件格式-Json基本语法

4. 标准 Json 文本里能不能写注释

题目

能在 .json 文件里像 C# 一样写 // 或块注释吗?Unity 里用 JsonUtility 读会怎样?

深入解析
  • 标准 Json:不允许注释;带 // 的文本整体非法。
  • **Unity JsonUtility**:按标准解析,遇到注释会失败。
  • 工程习惯:说明写在单独文档或字段里;草稿可用 jsonc 高亮,发布资源前删掉注释
答题示例

标准 Json 没有注释,JsonUtility 也不能读带 // 的文件。

真要说明用额外字段或文档;临时用带注释草稿可以,进包前要清掉。

参考文章
  • 2.Json文件格式-Json基本语法

5. JsonUtility 序列化自定义类型时特性怎么加

题目

JsonUtility.ToJson 序列化你自己写的 C# 类时,[System.Serializable][SerializeField] 分别在什么场景必须加?

深入解析
  • 参与序列化的类型一般要标 [System.Serializable],否则 Unity 序列化路径不认(最外层有时能凑合,但正文建议该加都加)。
  • public 字段默认会进 Json;private / protected 要进 Json 必须加 [SerializeField]
  • 这与 LitJson 不同:LitJson 不认这套特性,只看 public。
答题示例

自定义类要加 [System.Serializable] 才能被 JsonUtility 正常序列化。

public 字段默认会输出;私有或受保护字段想进 Json 要再加 [SerializeField]

参考文章
  • 4.CSharp操作Json-JsonUtility

进阶题

1. Json 和 Xml 的对比一般会从哪些工程维度切入

题目

如果面试官让你对比 Json 与 Xml,你会从哪些角度回答,并各说一条典型取舍?

深入解析
  • 体积与带宽:同样信息量,Json 往往更紧凑,移动端和接口场景更常见;Xml 带大量标签时冗余更明显。
  • 人读与手写:Json 花括号与键值对更轻;Xml 标签成对、可带属性,某些配置习惯用 Xml。
  • 解析与生态:两种都有成熟解析器;Unity 内置 JsonUtility 只面向 Json,Xml 则走另一套 API,选型要和团队规范、已有资产格式对齐。
  • 注意:具体项目里还有 Schema、注释、CDATA、混合内容等细节,回答时承认「要看协议与工具链」,比背死结论更稳。
答题示例

会从体积、可读性、解析成本和团队现有格式来比。

Json 一般在网络与轻量配置里更省流量、写法简单;Xml 在需要强 Schema、老系统或特定工具链时仍有地盘。Unity 侧 Json 常用 JsonUtility 或第三方库,Xml 是另一套读写路径,选型要跟项目资产和协议一致。

参考文章
  • 1.概述

2. Excel 网页转 Json 为什么还要人工检查

题目

把 Excel 复制到在线工具生成 Json,直接进项目可能出什么问题?你会检查哪些方面?

深入解析
  • 类型:数字被当成字符串、布尔被当成 "true" 文本、浮点精度被截断。
  • 结构:合并单元格、空行、表头多行导致键名怪异或缺列。
  • 内容:引号、换行、逗号未转义破坏 Json 结构。
  • 做法:diff 旧表、抽样跑解析、关键字段做单元测试或校验脚本。
答题示例

自动转换不保证类型和结构都对,可能数字变字符串、合并格搞乱列。

我会肉眼看一遍关键列,能跑解析器加载一遍更好,必要时写小脚本校验 id、数值范围。

参考文章
  • 3.Json文件格式-Excel转Json

3. JsonUtility 为什么不能直接把 [{...},{...}] 反序列化成 List

题目

Excel 导出的配表 Json 顶层是对象数组,为什么 JsonUtility.FromJson<List<RoleInfo>>(jsonStr) 会报错?正文里的做法是什么?

深入解析
  • JsonUtility 只把 Json 根节点当「一个对象」来填进一个 C# 类型;根是 [ 开头的数组时,与「单个对象」模型对不上。
  • 做法:定义 class RoleData { public List<RoleInfo> list; },并把磁盘上的 Json 改成 {"list":[...]} 这种对象包数组,再 FromJson<RoleData>
答题示例

JsonUtility 要求根是对象,不能直接对顶层数组 FromJson 成 List。

要包一层壳类,Json 里用字段名包住数组,比如 list 对应 List<RoleInfo>

参考文章
  • 4.CSharp操作Json-JsonUtility

4. LitJson 反序列化为什么强调无参构造函数

题目

LitJson 把 Json 转成自定义类实例时,对类的构造函数有什么要求?没有会怎样?

深入解析
  • 反序列化要先 new 出目标类型再填字段,LitJson 依赖 无参构造函数 创建实例。
  • 只有带参构造、且未显式写无参构造时,ToObject<T> 往往直接异常。
  • 带参构造可以保留,但需额外写 public ClassName() { } 给反序列化用。
答题示例

LitJson 反序列化要用无参构造先创建对象再填字段。

没有无参构造会报错;可以保留带参构造,但要自己补一个 public 无参构造。

参考文章
  • 5.CSharp操作Json-LitJson

深度题

1. 如何把 Excel 到 Json 从手工复制升级成可靠管线

题目

策划继续用 Excel 配表,你希望减少「复制网页→手粘 json」的错误;从工程角度你会怎么设计流程与门禁?

深入解析
  • 一键导出:编辑器菜单、命令行或 CI 调用脚本(Python、C#、Node 等)读 xlsx 输出 .json,版本与输出路径固定。
  • 校验:导出后做 Schema 或自定义规则检查(必填列、类型、id 唯一);失败则打断构建。
  • 与运行时衔接:约定顶层是数组还是包一层对象,与 JsonUtility/LitJson 的反序列化类型一致;大表考虑分文件或 Addressables。
  • 回滚与 diff:Json 进版本库,PR 里能看配表差异;严重错误可快速回滚。
答题示例

我会做一键导出脚本,保存 Excel 就生成 Json,避免人手复制。

导出后加校验:类型、唯一 id、必填字段,不通过不让进包;Json 进 Git 方便 diff。运行时类型跟导出约定对齐,减少反序列化翻车。

参考文章
  • 3.Json文件格式-Excel转Json

2. Unity 项目里 JsonUtility 和 LitJson 怎么选

题目

同样读存档或配表 Json,什么情况下你优先 JsonUtility,什么情况下换 LitJson?各说一条风险或成本。

深入解析
  • JsonUtility:零第三方、IL2CPP 等场景省心;但字典不支持、顶层数组要壳类、null 与 float 表现要心里有数。
  • LitJson:字典、顶层 List/[]、少写特性、null 更直观;但要维护拷贝的源码版本,且只能序列化 public、无参构造约束。
  • 与正文一致:按需求选,结构复杂时倾向 LitJson;简单对象且想依赖官方 API 时用 JsonUtility。
答题示例

只要简单对象、愿意包一层壳、不想引第三方,用 JsonUtility。

要字典、顶层数组、少写特性、null 要准确,用 LitJson,但要接受拷源码和只序列化 public、无参构造的限制。

参考文章
  • 6.CSharp操作Json-JsonUtility和LitJson对比


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

×

喜欢就点赞,疼爱就打赏