如何将Excel题库转为SwiftUI项目所需结构JSON及SylabusItem抽题
Excel题库转目标结构JSON的操作流程
能否一步完成
没有绝对的一步到位方案:如果从最开始整理Excel时就完全对齐目标JSON的嵌套结构(比如同个SylabusItem的题目用合并单元格归组,列名、字段类型和目标JSON完全匹配),可以实现导出即得目标文件;如果是已经整理好的平铺式Excel原始表,通常需要2-3步操作,出错率更低。
具体操作步骤
- 第一步:Excel数据规范化预处理
- 统一映射字段名:把Excel里的表头和目标JSON的字段一一对应,比如原表的“知识点模块”直接命名为
sylabusItem,“题干”命名为questionContent,所有选项、正确答案、解析等列名严格对齐目标格式,避免后续转换时字段错位 - 清理无效数据:删除重复题目、空行、单元格内的特殊转义字符(比如Excel自带的换行符、全角双引号,这类字符如果不清理,导出的JSON会触发语法错误)
- 统一归组标识:给同属一个SylabusItem的题目打上完全一致的标识(比如统一用知识点编码作为标识,不要出现同个考点一会写“Swift闭包”一会写“闭包语法”的不一致写法,避免分组时把同个知识点的题拆成多个组)
- 统一映射字段名:把Excel里的表头和目标JSON的字段一一对应,比如原表的“知识点模块”直接命名为
- 第二步:格式转换生成JSON
- 低代码方案:用本地离线的表格转JSON工具,导出时选择“按指定字段生成嵌套数组结构”,把SylabusItem作为分组键,同组的题目自动聚为该节点下的题目集合;导出时开启“特殊字符自动转义”选项,确认数字类型的题目ID、序号不要被转成字符串,匹配目标JSON的字段类型
- 批量更新高效方案:如果后续需要经常更新题库,可以写个短的本地Python脚本,用pandas读取Excel表格,按SylabusItem字段做分组聚合,把同组题目聚成嵌套数组后,用内置json库导出格式化的JSON文件,全程本地运行不会泄露题库数据
- 第三步:结果校验
把导出的JSON放到本地格式校验工具里检查语法错误,逐一核对每个SylabusItem下的题目数量是否和Excel里的统计数一致,有没有漏题、错归组的问题,确认结构完全匹配项目要求后再导入Xcode项目。
SwiftUI 端按SylabusItem动态抽题的实现思路
- 先打牢数据基础:按照目标JSON的结构定义两个遵循
Codable协议的模型,一个是SylabusItem,包含知识点ID、标题,以及该知识点下的所有题目数组questions: [Question];另一个是Question模型,包含题干、选项、正确答案等业务需要的字段。JSON加载完成后直接解码为[SylabusItem]数组,存在独立的ViewModel里,不要把文件读取、数据处理的逻辑直接写在View层。 - 抽题逻辑封装在ViewModel中,写可复用的通用方法:方法接收两个入参,一个是目标SylabusItem的ID,另一个是需要抽取的题目数量n,返回抽好的题目数组
- 核心逻辑的注意事项:
- 加边界判断:先校验目标SylabusItem下的题目总数是否大于等于需要抽取的n,如果总题数不足,就返回该知识点下的全部题目,避免数组越界崩溃
- 随机打乱取数:把对应SylabusItem下的题目数组先做随机打乱,再取前n个元素作为最终展示的题目,避免每次考试的题目顺序完全固定
- 灵活调整抽题规则:单独维护一个配置字典,key是各个SylabusItem的ID,value是对应需要抽取的题目数量,后续调整不同知识点的抽题数时,只需要修改这个配置字典即可,不用改动核心抽题代码
- 简化示例代码(适配新手场景):
class ExamViewModel: ObservableObject { // 存储所有知识点及对应题目,从JSON解码而来 var sylabusList: [SylabusItem] = [] func pickQuestions(from sylabusID: String, count: Int) -> [Question] { // 找到对应知识点 guard let targetSylabus = sylabusList.first(where: { $0.id == sylabusID }) else { return [] } // 边界处理:如果需要抽取的数量大于总题数,就返回全部题目 let validPickCount = min(count, targetSylabus.questions.count) // 打乱顺序后取对应数量的题目 return Array(targetSylabus.questions.shuffled().prefix(validPickCount)) } }
- 新手避坑提示:不要在JSON刚加载的时候就把所有题目全局打乱,一定要按照每个SylabusItem的独立题集做打乱和抽取,避免跨知识点的题目混杂到一起。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

