[quick note]
Handlebars 升級到 4.6 之後,會限制傳入的資料規格,不允許帶有 prototype properties 的物件。
From version 4.6.0 on, Handlebars forbids accessing prototype properties and methods of the context object by default. The reason are various security issues that arise from this possibility. The following options can be used to control this access.
(Ref: https://handlebarsjs.com/api-reference/runtime-options.html)
雖然仍然給予使用者調整限制的權限,不過官方不建議自己調整。
因此,當我們透過 Sequelize 從資料庫取出資料之後,需要讓他變成 pure object,目前已知有以下幾種做法
在 query option 當中設定 raw: true
let users = await User.findAll({ raw: true, nest: true })
這個方法適合所有的查詢方式,特別是多筆資料的查詢。
取出 dataValue
let user = await User.findOne({ where: { id: req.user.id } })
user = user.dataValue
用 .get() 方法
let user = await User.findOne({ where: { id: req.user.id } })
user = user.get()
以上兩個方法適用在只取出一筆資料的情況。另外,其實 .get()
本身其實就是回傳 sequelize instance 的 dataValue。
.get()
原本的使用方式是,可以透過傳入欄位 key 值,取得欄位的 value,譬如:
let user = await User.findOne({ where: { id: req.user.id } })user = user.get('name') // 'td'
不過如果沒有傳入 key 值,就會回傳整個查詢結果的 dataValue
用 .toJSON() 方法
let user = await User.findOne({ where: { id: req.user.id } })
user = user.toJSON()
如果查看原始碼,其實他也只是呼叫了 .get()
,只不過傳入了額外的 option
Instance.prototype.toJSON = function() {
return this.get({
plain: true
});
};
也就是說,其實使用 .toJSON()
的結果,跟單純使用 .get()
的結果應該會不一樣!
我目前觀察到的差別在,如果取出的資料有包含關聯資料,使用 .get()
只會「刪去」主資料繼承而來的屬性,但關聯資料當中繼承而來的屬性還會存在。如果使用 .toJSON()
,那麼連關聯資料當中繼承而來的屬性也會一併消失。
(😳 等等,如果關聯資料裡面還有繼承而來的屬性,那這樣還叫做 pure object 嗎 😳)
JSON.parse() & JSON.stringify()
最後,當然也可以用 JavaScript 原生的 JSON 方法
let user = await User.findOne({ where: { id: req.user.id } })
user = JSON.parse(JSON.stringify(user))
效果跟先前提到的 .toJSON()
一模一樣
最後記得,如果要對資料進行修改、刪除,記得不要將資料轉成 pure object,否則會無法使用 sequelize instance 當中的方法對資料庫進行正確的操作。
About me
Self-taught and trained in software development knowledge and skills, I am passionate about creating changes through technology.
Find more at Github
, LinkedIn
, Teaching at ALPHA Camp