ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AdminJS flat.get 完全指南:从扁平化 params 中安全提取嵌套属性

AdminJS flat.get 完全指南:从扁平化 params 中安全提取嵌套属性 后端低代码【免费下载链接】adminjsAdminJS is an admin panel for apps written in node.js项目地址https://gitcode.com/gh_mirrors/ad/adminjs点击查看免费下载本文聚焦 AdminJS 数据模型的核心机制——扁平化flatten存储深入讲解flat.get()工具函数的完整用法、底层实现原理含includeAllSiblings选项与数组兄弟节点处理以及它在BaseRecord、前端组件和参数预处理中的实际应用帮助你准确、安全地从扁平化 params 中提取任意层级的嵌套数据。为什么 AdminJS 需要 flat.get扁平化数据模型Flatten ParamsAdminJS 在后端把所有来自数据库表/集合的数据存入BaseRecord的params对象中通常是一个{key: value}结构在前端则对应RecordJSON.params。简单情况下它长这样params: { name: John, surname: Doe, age: 28, }但在真实业务中数据库往往存在嵌套的 JSONB 属性或 Mixed Schema开发者还会向前端/后端发送数组等复杂结构。因此 AdminJS 采用“扁平化”方案在保存到params之前把嵌套对象与数组全部拍平用.分隔路径分隔符定义在 src/utils/flat/constants.ts值为.params: { name: John, surname: Doe, age: 28, // nested objects auth.facebook: some login token, auth.twitter: twitter login token, // arrays interests.0: running, interests.1: jogging, }为什么要拍平两条硬核理由数据库局部更新若直接保存整个原始对象Model.save({ auth: { facebook: newFacebookToken } })ORM 会整体覆盖auth字段从而丢失auth.twitter而保存扁平形式Model.save({ auth.facebook: newFacebookToken })则可保留同层其他键值。这一点在 Mongoose 适配器最擅长处理 mixed values中体现得最明显。前后端 FormData 传输AdminJS 支持前端上传文件到后端最优方式是使用 FormData它要求所有字段值为[key: string]: string形式恰好与扁平化 params 完美契合。正因为如此BaseRecord与RecordJSON中你拿到的都不是原始对象而是扁平版本此时就需要flat模块提供的一组辅助函数详见 src/utils/flat/flat.doc.md。flat.get 函数签名与基本用法flat.get在 src/utils/flat/get.ts 中实现并通过 src/utils/flat/flat-module.ts 挂载到flat命名空间导出flat模块自 AdminJS 3.3 版本引入。类型定义位于 src/utils/flat/flat.types.tsconst get (params: FlattenParams {}, propertyPath?: string, options?: GetOptions): any参数说明参数类型必填说明paramsFlattenParams是有默认值{}扁平化参数对象键为路径字符串值为基本类型、Date、null、空数组、空对象或FilepropertyPathstring否要提取的属性路径如education.school不传则返回整个反扁平化unflatten对象optionsGetOptions否可选配置目前仅含includeAllSiblingsFlattenValue支持的类型联合见 src/utils/flat/flat.types.tsstring、boolean、number、Date、null、[]空数组、{}空对象以及File。基础示例原文档给出的典型场景src/utils/flat/get.doc.mdimport flat from adminjs const params { name: John, education.school.name: Harvard, education.school.id: 123, } const data flat.get(params, education.school) // results to { // name: Harvard, // id: 123, // } // 不传 propertyPath 时返回整个反扁平化对象 const data flat.get(params) // results to { // name: John, // education: { // school: { // name: Harvard, // id: 123, // } // } // }注意flat.get(params)内部直接调用flat.unflatten(params)get.ts即“取出全部并还原为嵌套对象”flat.unflatten与flat.flatten一样直接来自 npmflat包见 flat-module.ts。查找规则先精确匹配再前缀匹配flat.get的查找策略分两步get.ts精确命中优先若params中已存在与propertyPath完全相等的键则直接返回params[propertyPath]。源码特意注释说明不能用typeof params[propertyPath] ! undefined判断因为属性值本身可能是undefined那样会误返回[undefined]。前缀匹配兜底未精确命中时通过propertyKeyRegexsrc/utils/flat/property-key-regex.ts构造正则再用selectParamssrc/utils/flat/select-params.ts筛出所有以该路径开头的扁平键把它们改写到临时键TEMP_HOLDING_KEY下最后整体unflatten并取出该临时键对应的值。若没有任何匹配键返回undefined。propertyKeyRegex生成的匹配模式形如^path($|\.)保证只匹配“以 path 为完整路径段开头”的键因此flat.get(params, interest.Of)不会误命中interest.OfMe.0这一点有专门测试用例验证见 get.spec.ts。边界行为一览以测试用例为准src/utils/flat/get.spec.ts 用一组完整用例界定了flat.get的边界行为普通标量get(params, name)直接返回该值不存在的属性返回undefined例如get(params, nameNotExisting)值为undefined的属性同样返回undefined嵌套数组get(params, interest.OfMe)还原出[javascript, typescript, brainTumor]嵌套对象含数组get(params, interest)还原出{ OfMe: [...] }null值get(params, nulled)返回nullnull属于合法FlattenValue不会被吞掉多级嵌套数组get(params, nested.0.el)得到[{ value: val0.0 }, { value: val0.1 }]。includeAllSiblings跨兄弟节点提取数组元素问题场景当属性路径中只给出一个数组索引、但期望提取所有兄弟索引的数据时普通前缀匹配是不够的。假设扁平键为nested.0.el.0.value / nested.0.el.1.value nested.1.el.0.value / nested.1.el.1.value如果调用get(params, nested.el)它只会命中nested与el之间的固定分隔符无法覆盖nested.0.el与nested.1.el两组数据。GetOptions.includeAllSiblings正是为此设计类型注释见 src/utils/flat/flat.types.ts。底层处理开启includeAllSiblings后propertyKeyRegex会把路径中的每个.替换为(\.|\.\d\.)即“普通分隔符或带索引的分隔符”从而让nested.el同时匹配nested.0.el、nested.1.el见 property-key-regex.ts。在 get.ts 中因为不同兄弟节点内部存在相同的子索引如两处都有.0.value直接 unflatten 会导致键冲突因此源码按枚举顺序把索引重写为连续编号nested.0.el.0.value、nested.0.el.1.value、nested.1.el.0.value、nested.1.el.1.value分别变为TEMP_HOLDING_KEY.0.value、.1.value、.2.value、.3.value再统一还原。最终flat.get(params, nested.el, { includeAllSiblings: true }) // 返回 [ { value: val0.0 }, { value: val0.1 }, // { value: val1 }, { value: val2 } ]该行为由测试用例 get.spec.ts 验证另外处理嵌套引用 ID 的用例get.spec.ts表明对于Skills.hardSkills.0.Profession这类嵌套引用flat.get(params, Skills.hardSkills.Profession, { includeAllSiblings: true })会返回[referenceId]这正是从扁平数据中批量收集引用字段的标准姿势。在 AdminJS 中的实际调用点1. BaseRecord 的取值入口src/backend/adapters/record/base-record.ts 中BaseRecord#get(propertyPath?, options?)直接透传flat.get(this.params, propertyPath, options)其 JSDoc 示例明确说明当params { genre.0: male, genre.1: female }时get(genre)返回[male, female]。因此所有基于BaseRecord的属性读取本质上都由flat.get完成。同文件中旧的param(path)方法已标记 deprecated也调用flat.get(this.params, path)base-record.ts。2. 前端属性型组件flat.get(record.params, property.path)是前端渲染扁平数据的事实标准例如数组型属性的编辑/列表/展示组件edit.tsx、list.tsx、show.tsx 均用flat.get(record.params, property.path) || []兜底空数组Key-Value 型属性edit.tsx 与 show.tsx 用?? {}兜底空对象引用型属性reference/edit.tsx 用flat.get(record?.params, property.path)提取引用 ID。3. 参数预处理src/utils/param-converter/prepare-params.ts 在把请求参数转换给后端属性时通过flat.get(params, property.path())读取对应属性的值保证嵌套字段在前后端之间流转时保持一致。使用建议与注意事项不传propertyPath即整体还原代价是返回整个嵌套对象数据量大时注意性能与内存优先让includeAllSiblings与数组型属性配合当属性路径中间存在索引段如nested.el对应nested.0.el、nested.1.el时务必开启否则取不到数据null、空数组、空对象会被原样返回可用?? {}或|| []按需兜底避免渲染报错值为undefined的属性返回undefined与“键不存在”行为一致判断时无需区分。延伸阅读flat模块整体说明与数据模型背景src/utils/flat/flat.doc.md配套辅助函数set.ts写入、remove-path.ts删除路径、select-params.ts筛选前缀参数、path-to-parts.ts路径切分、merge.ts合并实现与测试get.ts、get.spec.ts赞分享后端低代码【免费下载链接】adminjsAdminJS is an admin panel for apps written in node.js项目地址https://gitcode.com/gh_mirrors/ad/adminjs点击查看免费下载相关推荐OBS源录制插件怎么用一个过滤器让每个画面单独出片OBS源录制插件怎么用一个过滤器让每个画面单独出片 你是不是也遇到过这样的尴尬OBS里排好的场景里摄像头和游戏画面挤在同一个视频里想单独剪一条摄像头素材后端低代码Buzz揭秘开源离线音频转录引擎的架构设计与技术实现Buzz揭秘开源离线音频转录引擎的架构设计与技术实现 Buzz 是一款基于 OpenAI Whisper 的离线音频转录与翻译工具为开发者提供了完全本地化的后端低代码RxJS 4 pluck 操作符完全指南从嵌套对象中安全提取属性值RxJS 4 pluck 操作符完全指南从嵌套对象中安全提取属性值 导读 pluck 是 RxJSReactive Extensions for JavaS后端上一篇PiliPlus解锁B站无限可能打造你的专属视频体验终极方案下一篇TrafficMonitor插件终极指南如何在Windows任务栏轻松监控系统性能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表