Ember:如何将任意哈希的短横线命名键序列化为驼峰式?
在Ember模型中将短横线分隔的哈希键转为驼峰式命名
这个需求在Ember开发里挺常见的,我给你分享两种靠谱的实现方式,你可以根据自己的场景选:
方法1:自定义属性转换(Transform)
这种方式最通用,适合多个模型都需要处理这类哈希的场景,相当于封装了一个可复用的转换工具。
步骤1:创建自定义Transform文件
在app/transforms/目录下新建camel-case-object.js,代码如下:
import Transform from '@ember-data/serializer/transform'; // 短横线转驼峰的工具函数 function dashToCamel(str) { return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase()); } // 驼峰转短横线的工具函数(如果需要把数据传回后端时还原格式) function camelToDash(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase(); } // 递归处理所有层级的对象/数组键名 function transformKeys(obj, transformFn) { if (typeof obj !== 'object' || obj === null) { return obj; } if (Array.isArray(obj)) { return obj.map(item => transformKeys(item, transformFn)); } return Object.keys(obj).reduce((acc, key) => { const newKey = transformFn(key); acc[newKey] = transformKeys(obj[key], transformFn); return acc; }, {}); } export default class CamelCaseObjectTransform extends Transform { deserialize(serialized) { // 后端返回的短横线键 → 转成驼峰供前端使用 return transformKeys(serialized, dashToCamel); } serialize(deserialized) { // 前端的驼峰键 → 转回短横线传给后端(可选,根据后端需求决定) return transformKeys(deserialized, camelToDash); } }
步骤2:在模型中使用这个Transform
修改你的模型文件,把原来的DS.attr('object')换成自定义的camel-case-object类型:
// app/models/your-model.js import Model, { attr } from '@ember-data/model'; export default class YourModel extends Model { @attr('camel-case-object') customHash; }
这样处理后,你在模板或组件里就能直接用驼峰式访问了,比如model.customHash.loremIpsum,不用再写model.customHash['lorem-ipsum']。如果需要把数据发回后端,serialize方法会自动把键转回短横线格式,完美兼容后端要求。
方法2:通过序列化器(Serializer)处理
如果这个哈希只是某个特定模型的属性,你也可以直接在该模型的序列化器里处理,针对性更强。
比如你的模型是Post,新建或修改app/serializers/post.js:
import RESTSerializer from '@ember-data/serializer/rest'; // 短横线转驼峰工具函数 function dashToCamel(str) { return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase()); } // 递归转换哈希键 function transformToCamel(obj) { if (typeof obj !== 'object' || obj === null) return obj; if (Array.isArray(obj)) return obj.map(transformToCamel); return Object.keys(obj).reduce((acc, key) => { acc[dashToCamel(key)] = transformToCamel(obj[key]); return acc; }, {}); } // 驼峰转短横线(用于序列化回后端) function camelToDash(str) { return str.replace(/([A-Z])/g, '-$1').toLowerCase(); } function transformToDash(obj) { if (typeof obj !== 'object' || obj === null) return obj; if (Array.isArray(obj)) return obj.map(transformToDash); return Object.keys(obj).reduce((acc, key) => { acc[camelToDash(key)] = transformToDash(obj[key]); return acc; }, {}); } export default class PostSerializer extends RESTSerializer { normalize(modelClass, resourceHash, prop) { // 处理模型里的customHash属性 if (resourceHash.customHash) { resourceHash.customHash = transformToCamel(resourceHash.customHash); } return super.normalize(modelClass, resourceHash, prop); } serialize(snapshot, options) { let json = super.serialize(snapshot, options); // 把驼峰键转回短横线传给后端(可选) if (json.customHash) { json.customHash = transformToDash(json.customHash); } return json; } }
这种方法不需要修改模型的属性定义,直接在序列化器里拦截数据处理即可,适合只需要在单个模型里处理的场景。
小提示:不管用哪种方法,一定要确保工具函数支持递归转换,不然嵌套的对象或数组里的键不会被处理哦!
内容的提问来源于stack exchange,提问作者karthikaruna
相关产品推荐
相关产品推荐

