新闻详情

新闻详情

首页 / 资讯中心 / 详情

Mongoose 自定义类型转换(Custom Casting)完全指南:用 SchemaType.cast() 覆盖内置 Casting

发布时间:2026/9/10 21:57:14来源:尧图网络
Mongoose 自定义类型转换(Custom Casting)完全指南:用 SchemaType.cast() 覆盖内置 Casting
Mongoose 自定义类型转换Custom Casting完全指南用 SchemaType.cast() 覆盖内置 Casting【免费下载链接】mongooseMongoDB object modeling designed to work in an asynchronous environment.项目地址: https://gitcode.com/GitHub_Trending/mo/mongoose本指南讲解 Mongoose 的**自定义类型转换Custom Casting**机制——通过SchemaType.cast()全局覆盖某个 SchemaType 的内置转换函数从而让类型转换规则完全贴合业务需求。文中以“把日文数字字符串二转成数字2”为主线案例并深入 lib/schemaType.js、lib/schema/number.js、lib/cast/number.js 等源码剖析自定义转换的底层调用链与错误包装机制。读完你将掌握Mongoose 内置转换何时会失败、如何无侵入地覆盖默认转换、如何委托原函数、如何彻底禁用转换以及如何在全局与单个 SchemaType 实例两个层面定制转换行为。什么是 Casting为什么需要自定义在 Mongoose 中**Casting类型转换**指把传入的任意值如 HTTP 请求里的字符串、表单提交的文本转换成 Schema 中声明的目标类型的过程。例如 Schema 声明age: Number时Mongoose 会在赋值、校验、查询时尝试把值转换为数字。Mongoose 5.4.0 起引入了若干种全局配置 SchemaType的能力其中就包括SchemaType.cast()这个函数它允许开发者覆盖 Mongoose 内置的转换逻辑。内置转换是“尽力而为”的它覆盖了字符串数字、布尔值、包装对象等常见情况但无法覆盖所有业务场景。例如默认情况下 Mongoose 无法把包含日文数字的字符串二转换为数字会直接抛出转换失败错误CastError。默认行为日文数字触发 CastError先看默认行为。声明age: Number后给文档赋值为字符串二并执行同步校验const schema new mongoose.Schema({ age: Number }); const Model mongoose.model(Test, schema); const doc new Model({ age: 二 }); const err doc.validateSync(); // Cast to Number failed for value 二 (type string) at path age err.message;validateSync()返回的err.message会包含类似Cast to Number failed for value 二 (type string) at path age的信息。也就是说字符串二无法被内置的数字转换函数接受校验失败。这条行为同样被仓库测试锁定test/docs/custom-casting.test.js 中的casting error用例断言了错误信息中必须包含Cast to Number failed for value 二 (type string) at path age。全局覆盖mongoose.Number.cast(fn)SchemaType的子类如Number上都挂载了静态的cast()方法它同时承担“读取”与“写入”两个职责无参数调用mongoose.Number.cast()返回当前生效的转换函数即原来的内置转换。传入函数调用mongoose.Number.cast(fn)设置新的转换函数此后所有 Number 路径的转换都会走fn。于是可以这样为数字类型扩展“日文数字”支持// 先保存当前内置的转换函数 const originalCast mongoose.Number.cast(); // 用自定义函数覆盖遇到 二 返回 2其余委托给内置转换 mongoose.Number.cast(v { if (v 二) { return 2; } return originalCast(v); }); const schema new mongoose.Schema({ age: Number }); const Model mongoose.model(Test, schema); const doc new Model({ age: 二 }); const err doc.validateSync(); err; // null —— 校验通过 doc.age; // 2 —— 已被转换为数字关键点有两个先取出原函数再委托const originalCast mongoose.Number.cast()拿到内置转换自定义函数对无法识别的值调用originalCast(v)走原有逻辑避免破坏默认行为。覆盖是全局的该设置在mongoose实例或mongoose单例层面生效之后新建的所有 Schema 中的 Number 路径都会使用新转换。该用例在 test/docs/custom-casting.test.js 中由casting override测试验证断言err为null且doc.age 2。彻底禁用转换cast(false) 与严格模式除了传入自定义函数cast()还支持传入false来完全关闭该类型的转换。在 lib/schema/number.js 中SchemaNumber.cast function cast(caster) { if (arguments.length 0) { return this._cast; } if (caster false) { caster this._defaultCaster; } this._cast caster; return this._cast; };传入false时会回退到_defaultCaster——一个只接受number类型、其余一律抛错的严格函数SchemaNumber._defaultCaster v { if (typeof v ! number) { throw new Error(); } return v; };也就是说// 禁用 Number 的一切隐式转换 mongoose.Number.cast(false); // 之后即使传 123 这样的纯数字字符串也会抛错只有真正的 number 才能通过这一点在 lib/schemaType.js 的基类实现里略有不同基类的false回退为v v恒等函数原样返回而 Number 的false回退为只接受number的严格校验器。因此“禁用转换”的语义因类型而异使用前应结合目标类型的实现确认。官方文档注释也给出了这一用法见 lib/schema/number.jsmongoose.Number.cast(false)等价于“完全禁用转换”与之对应还可以用mongoose.Number.cast(v { if (v ) { return 0; } return original(v); })让空字符串转换为0。实例级定制castFunction()上面的cast()是类构造器级别的影响该类型的所有路径。若只想影响某一个 SchemaType 实例某一条具体路径可以使用SchemaType.prototype.castFunction()lib/schemaType.jsconst number new mongoose.Number(mypath, {}); number.castFunction(v { // 只影响 mypath 这条路径只允许 number 或 undefined assert.ok(v undefined || typeof v number); return v; });castFunction(caster, message)同样支持无参读取、传false回退到默认、传字符串设置自定义错误消息。在 lib/schema/number.js 的实例cast()方法中可以看到两者的优先级优先使用实例级this._castFunction其次回退到构造器级this.constructor.cast()返回的全局转换函数。这意味着你可以先用mongoose.Number.cast()做全局兜底再对个别路径用castFunction()做细粒度覆盖。底层原理转换失败如何变成 CastError自定义转换的执行链路可以从 lib/schema/number.js 的实例cast()方法看清SchemaNumber.prototype.cast function(value, doc, init, prev, options) { // 1. 处理引用populate ref与文档对象取 value._id if (typeof value ! number SchemaType._isRef(this, value, doc, init)) { if (value null || utils.isNonBuiltinObject(value)) { return this._castRef(value, doc, init, options); } } const val value?._id ! undefined ? value._id : value; // 2. 选择转换函数实例级优先其次构造器级 let castNumber; if (typeof this._castFunction function) { castNumber this._castFunction; } else if (typeof this.constructor.cast function) { castNumber this.constructor.cast(); } else { castNumber SchemaNumber.cast(); } // 3. 执行转换抛出的任何错误统一包装为 CastError try { return castNumber(val); } catch (err) { throw new CastError(Number, val, this.path, err, this); } };由此可以看出转换函数的选择顺序是实例级_castFunction→ 构造器级cast()→ 兜底SchemaNumber.cast()自定义函数中throw的任何错误都会被捕获并重新包装为CastError(Number, ...)与 Mongoose 内置的报错风格保持一致对_id字段会先取出value._id再转换兼容传入文档对象的情况。内置的默认转换函数实现在 lib/cast/number.js其完整规则为输入值转换结果null/undefined原样返回视为合法空字符串返回null字符串 / 布尔值Number(val)转换NaN结果抛出Cast to Number failed: value is not a valid numberNumber包装对象返回valueOf()普通number直接返回带valueOf函数的对象Number(val.valueOf())带toString且能转成数字的对象返回Number(val)其余情况抛出Cast to Number failed: value is not a valid number这正是自定义转换“委托原函数”时的行为基准。不止 Number其他 SchemaType 同样支持cast()是SchemaType基类的能力因此String、Date、Boolean、ObjectId、Decimal128、Double、Int32等内置类型也都支持全局自定义转换。仓库测试给出了多处佐证test/schematype.cast.test.js对应 issue gh-7045覆盖了ObjectId、Boolean等类型的自定义转换例如对ObjectId自定义转换让字符串special映射到合法的 ObjectId同时保持基类Schema.ObjectId的行为不变通过子类继承实现隔离class CustomObjectId extends Schema.ObjectId {} CustomObjectId.cast(v { if (v special) { return original.objectid(0.repeat(24)); } return original.objectid(v); });同一文件还验证了Schema.ObjectId.cast(false)后000000000000000000000000这类字符串会抛出CastError只有真正的ObjectId实例能通过test/schematype.cast.test.js。test/double.test.js 与 test/int32.test.js 分别演示了Double.cast(fn)与Int32.cast(fn)的覆盖写法。test/schematype.test.js 展示了在 SchemaType 实例上直接调用schemaType.cast(...)的用法。这些测试都遵循同一模式先在beforeEach中保存原转换函数在afterEach中恢复避免测试间相互污染。使用注意事项全局覆盖影响所有 Schemamongoose.Number.cast(fn)一旦设置后续创建的所有使用Number的路径都会受影响已有 Schema 实例在创建时已捕获转换函数行为视具体版本而定。因此务必保存并委托原函数并在不再需要时恢复例如const originalCast mongoose.Number.cast(); mongoose.Number.cast(v /* 自定义逻辑 */); // ...业务代码... mongoose.Number.cast(originalCast); // 恢复错误会被包装成 CastError自定义函数里throw new Error(...)会在外层被包装为带路径信息的CastError见 lib/schema/number.js调用方可通过err.name CastError判断。禁用转换语义因类型而异cast(false)在基类回退为恒等函数在Number回退为“仅接受 number”的严格函数使用前应查看对应类型源码确认。实例级覆盖更安全如果只想影响单条路径优先使用SchemaType.prototype.castFunction()lib/schemaType.js避免污染全局。与校验、查询联动自定义转换同时作用于文档赋值/校验和查询条件查询走castForQuery见 lib/schema/number.js因此转换函数需要能够处理来自查询过滤器的值。延伸阅读教程原文docs/tutorials/custom-casting.md基类实现lib/schemaType.js静态cast、实例castFunction、原型castNumber 实现lib/schema/number.js构造器级cast与_defaultCaster、lib/schema/number.js实例cast与 CastError 包装内置转换函数lib/cast/number.js、lib/cast/string.js、lib/cast/boolean.js类型注册lib/mongoose.jsmongoose.Number SchemaTypes.Number测试用例test/docs/custom-casting.test.js、test/schematype.cast.test.js【免费下载链接】mongooseMongoDB object modeling designed to work in an asynchronous environment.项目地址: https://gitcode.com/GitHub_Trending/mo/mongoose创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Web渗透之联合查询注入全流程 2026/9/10 22:36:19

Web渗透之联合查询注入全流程

本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行,任何未经授权使用文中技术的行为均与作者无关,请务必遵守法律法规,获得许可后方可进行渗透测试。 目录 一、概念 1.SQL注入的概念 2.SQL注入的目的 二、注入点的数据类…

阅读更多 →
Storybook 手动为 React + Webpack 5 项目启用框架:`.storybook/main` 中 `@storybook/react-webpack5` 的完整配置指南 2026/9/10 22:36:19

Storybook 手动为 React + Webpack 5 项目启用框架:`.storybook/main` 中 `@storybook/react-webpack5` 的完整配置指南

Storybook 手动为 React Webpack 5 项目启用框架:.storybook/main 中 storybook/react-webpack5 的完整配置指南 【免费下载链接】storybook Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation 项…

阅读更多 →
(全新整理)上市公司每股社会贡献值2003-2023年 2026/9/10 22:36:19

(全新整理)上市公司每股社会贡献值2003-2023年

文章目录资料下载地址介绍01、数据介绍02、数据指标项目备注资料下载地址资料下载地址 点击这里下载资料 介绍 01、数据介绍 衡量上市公司对社会整体贡献程度的财务指标。简单来说,它不仅仅看公司为股东赚了多少钱,还综合考量了企业为国家、员工、债…

阅读更多 →
Ultralytics ONNX INT8 量化导出解析:基于 ONNX Runtime 静态量化的校准与实现指南 2026/9/10 22:36:19

Ultralytics ONNX INT8 量化导出解析:基于 ONNX Runtime 静态量化的校准与实现指南

Ultralytics ONNX INT8 量化导出解析:基于 ONNX Runtime 静态量化的校准与实现指南 【免费下载链接】ultralytics Ultralytics YOLO26, YOLO11, YOLOv8 — object detection, instance segmentation, semantic segmentation, image classification, pose estimation…

阅读更多 →
(全新整理)省级与地级市人工智能关注度2011-2025年 2026/9/10 22:36:19

(全新整理)省级与地级市人工智能关注度2011-2025年

文章目录资料下载地址介绍01、数据介绍02、数据指标03、数据截图项目备注资料下载地址资料下载地址 点击这里下载资料 介绍 01、数据介绍 本研究借鉴参考郑世林(2021),计算出“人工智能”关键词在百度网页搜索中搜索频次的加权和,以衡量省、地级市的…

阅读更多 →
使用 V 语言 wasm 模块生成 WebAssembly 字节码:从零构建 .wasm 文件的完整指南 2026/9/10 22:33:19

使用 V 语言 wasm 模块生成 WebAssembly 字节码:从零构建 .wasm 文件的完整指南

使用 V 语言 wasm 模块生成 WebAssembly 字节码&#xff1a;从零构建 .wasm 文件的完整指南 【免费下载链接】v Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞