淺析如何使用JavaScript輕松實現(xiàn)數(shù)據(jù)轉換
之前寫了一篇 《TypeScript裝飾器之我們是這么處理項目數(shù)據(jù)轉換的》,有很多朋友私信和評論說,如果沒有 TypeScript
和 裝飾器
,純 JavaScript
有沒有什么好的數(shù)據(jù)轉換的方案呢?
很遺憾,還真有,雖然沒有 TypeScript
那么優(yōu)雅,但是也足夠好用。
這里用到了 Getter
/Setter
,以及 Object 原型鏈相關的知識。
一、假設需求
1. 后端返回的數(shù)據(jù)
這里我們先假設從后端來了個 JSON
長這樣:
{ id: 1, nickname: 'Hamm', age: 18, sex: 1, createTime: 1707021296000, bio: '一些廢話,前端不需要的字段' }
其中,id
createTime
是固定返回的公共屬性。
2. 前端類型聲明
基類
class BaseEntity { id; createTime; }
用戶類
class User extends BaseEntity { nickname; age; sex; }
3. 轉換要求
轉換到類時
createTime
轉為 Date類型;- 前端使用
gender
作為性別字段,且需要根據(jù)1/0
顯示男女; - 前端沒有
bio
字段,需要過濾掉。
轉換到 JSON 時
createTime
轉回后端需要的時間戳gender
還原回后段需要的sex
,并且轉換為1/0
二、實現(xiàn)思路
正如我們之前有篇關于 幾個有關Getter/Setter的小故事 文章中提到,我們可以用 getter
/setter
來攔截數(shù)據(jù)達到轉換數(shù)據(jù)的目的:
1. 基于基類實現(xiàn) fromJson 靜態(tài)方法
class BaseEntity { id; createTime; static fromJson(json) { const user = new this(); const filteredJson = Object.keys(json).reduce((item, key) => { if (user.hasOwnProperty(key)) { item[key] = json[key]; } if (user.__proto__.hasOwnProperty(key)) { item[key] = json[key]; } return item; }, {}); const entity = Object.assign(user, filteredJson); if (entity.createTime) { entity.createTime = new Date(entity.createTime); } return entity; } } class UserEntity extends BaseEntity { nickname; age; gender; get sex() { return this.gender; } set sex(value) { if (value === undefined || value === null) { this.gender = undefined }else{ this.gender = value === 1 ? '男' : '女'; } } } const json = { id: 1, nickname: 'Hamm', age: 18, sex: 1, createTime: 1707021296000, bio: '一些廢話,前端不需要的字段' } console.log("json", json) const user = UserEntity.fromJson(json) console.log("entity", user)
其中,我們通過讀取 getter
/setter
以及本身的屬性,來確定哪些是直接賦值,哪些是走set方法,哪些不存在的需要忽略。
2.調試輸出,美滋滋
json { id: 1, nickname: 'Hamm', age: 18, sex: 1, createTime: 1707021296000, bio: '一些廢話,前端不需要的字段' } entity UserEntity { id: 1, createTime: 2024-02-04T04:34:56.000Z, nickname: 'Hamm', age: 18, gender: '男' }
3. 實現(xiàn)動態(tài)方法的 toJson
接下來,我們需要將 BaseEntity
添加一個 toJson
方法,用于將實體轉換為 JSON 格式,且給 UserEntity
的 sex getter
做一下數(shù)據(jù)轉換:
class BaseEntity { id; createTime; static fromJson(json) { const user = new this(); const filteredJson = Object.keys(json).reduce((item, key) => { if (user.hasOwnProperty(key)) { item[key] = json[key]; } if (user.__proto__.hasOwnProperty(key)) { item[key] = json[key]; } return item; }, {}); const entity = Object.assign(user, filteredJson); if (entity.createTime) { entity.createTime = new Date(entity.createTime); } return entity; } toJson() { const proto = Object.getPrototypeOf(this); const ownProperties = Object.getOwnPropertyNames(this); const getters = Object.getOwnPropertyNames(proto).filter(key => { const descriptor = Object.getOwnPropertyDescriptor(proto, key); return descriptor && typeof descriptor.get === 'function'; }); const json = {} getters.forEach(key => { if (this.__proto__.hasOwnProperty(key)) { json[key] = this[key] this[key] = undefined } }) ownProperties.forEach(key => { if (this.hasOwnProperty(key)) { json[key] = this[key] this[key] = undefined } }) if (json.createTime && typeof json.createTime === 'object') { json.createTime = json.createTime.valueOf() } else { json.createTime = undefined } return JSON.parse(JSON.stringify(json)) } } class UserEntity extends BaseEntity { nickname; age; gender; get sex() { if (this.gender === undefined || this.gender === null) { return undefined } return this.gender === '男' ? 1 : 0; } set sex(value) { if (value === undefined || value === null) { this.gender = undefined }else{ this.gender = value === 1 ? '男' : '女'; } } } const user = new UserEntity() user.id = 1 user.nickname = "Hamm" user.age = 18 user.gender = "男" user.createTime = new Date() console.log("entity", user) console.log("json", user.toJson())
4. 繼續(xù)調試輸出,繼續(xù)美滋滋
entity UserEntity { id: 1, createTime: 2024-10-23T19:37:07.521Z, nickname: 'Hamm', age: 18, gender: '男' } json { sex: 1, id: 1, createTime: 1729712227521, nickname: 'Hamm', age: 18 }
三、完整代碼如下
class BaseEntity { id; createTime; static fromJson(json) { const user = new this(); const filteredJson = Object.keys(json).reduce((item, key) => { if (user.hasOwnProperty(key)) { item[key] = json[key]; } if (user.__proto__.hasOwnProperty(key)) { item[key] = json[key]; } return item; }, {}); const entity = Object.assign(user, filteredJson); if (entity.createTime) { entity.createTime = new Date(entity.createTime); } return entity; } toJson() { const proto = Object.getPrototypeOf(this); const ownProperties = Object.getOwnPropertyNames(this); const getters = Object.getOwnPropertyNames(proto).filter(key => { const descriptor = Object.getOwnPropertyDescriptor(proto, key); return descriptor && typeof descriptor.get === 'function'; }); const json = {} getters.forEach(key => { if (this.__proto__.hasOwnProperty(key)) { json[key] = this[key] this[key] = undefined } }) ownProperties.forEach(key => { if (this.hasOwnProperty(key)) { json[key] = this[key] this[key] = undefined } }) if (json.createTime && typeof json.createTime === 'object') { json.createTime = json.createTime.valueOf() } else { json.createTime = undefined } return JSON.parse(JSON.stringify(json)) } } class UserEntity extends BaseEntity { nickname; age; gender; get sex() { if (this.gender === undefined || this.gender === null) { return undefined } return this.gender === '男' ? 1 : 0; } set sex(value) { if (value === undefined || value === null) { this.gender = undefined }else{ this.gender = value === 1 ? '男' : '女'; } } } const json = { id: 1, nickname: 'Hamm', age: 18, sex: 1, createTime: 1707021296000, bio: '一些廢話,前端不需要的字段' } console.log("json",json) const user = UserEntity.fromJson(json) console.log("entity", user) console.log("json", user.toJson())
四、總結
如上代碼,我們利用了 getter/setter
以及 Object
原型鏈上的一些方法來完成了轉換。
雖然稍顯麻煩,但也算解決了不在外部寫一些方法來轉換。
各有所長,實現(xiàn)的方式有很多種,但思路才是很好玩的東西。
當然,JavaScript的裝飾器提案已經(jīng)快發(fā)布了,后續(xù)我們將繼續(xù)摸索用裝飾器在JavaScript中實現(xiàn)類似功能。(TypeScript的裝飾器我們敢用,是因為編譯后的JS代碼沒有包含裝飾器的部分,在瀏覽器上不會有問題。)
到此這篇關于淺析如何使用JavaScript輕松實現(xiàn)數(shù)據(jù)轉換的文章就介紹到這了,更多相關JavaScript數(shù)據(jù)轉換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IE6瀏覽器中window.location.href無效的解決方法
這篇文章主要介紹了IE6瀏覽器中window.location.href無效的解決方法,給出了正確與錯誤的實例對比,分析跳轉無效的原因與解決方法,是非常實用的技巧,需要的朋友可以參考下2014-11-11JavaScript利用canvas實現(xiàn)鼠標跟隨特效
canvas是一個很神奇的玩意兒,比如畫表格、畫海報圖都要用canvas去做。本文就來利用canvas制作個簡單的鼠標跟隨特效,快跟隨小編一起學習一下吧2022-10-10JavaScript中三種for循環(huán)語句的使用總結(for、for...in、for...of)
這篇文章主要給大家介紹了關于JavaScript中三種for循環(huán)語句的使用的相關資料,For循環(huán)用在需要重復執(zhí)行的某些代碼,本文介紹的三種for循環(huán)分別包括for、for...in、for...of,需要的朋友可以參考下2021-06-06使用JavaScript將圖片合并為PDF的實現(xiàn)
在日常工作中,我們可能需要拍攝一些照片并將圖像合并到PDF文件中,這可以通過許多應用來完成,Dynamsoft Document Viewer讓這一操作更加方便,在本文中,我們將使用Dynamsoft Document Viewer創(chuàng)建一個Web應用,用JavaScript將圖像合并到PDF中,需要的朋友可以參考下2024-07-07