使用acorn语法解析器来获取model里的key
获取model里的key
比如model定义
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var MongooseDao = require('mongoosedao')
var courseSchema = new Schema({
name: { type: String, unique: true }, //课程名称
category: String, //分类(/首页/人工智能/系统掌握深度学习)
price: String, //价格
picture: String, //头图
})
var course = mongoose.model('Course', courseSchema)
var courseDao = new MongooseDao(course)
module.exports = courseDao
能想到的做法
- 正则匹配分组,然后再处理
- 采用js的语法解释器
很明显后者是更好的方式。推荐使用https://github.com/ternjs/acorn,它是一个“A small, fast, JavaScript-based JavaScript parser”。非常好用。babel的语法也是基于acorn的。
acorn示例
const acorn = require("acorn")
const walk = require("acorn/dist/walk")
walk.simple(acorn.parse("let x = 10"), {
Literal(node) {
console.log(`Found a literal: ${node.value}`)
}
})
再看我的需求,获取model里定义的所有key。先最小化,看看生成的ast内容
var courseSchema = new Schema({
a:1
})
对应的http://astexplorer.net/上的测试结果
{
"type": "Program",
"start": 0,
"end": 42,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 42,
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 42,
"id": {
"type": "Identifier",
"start": 4,
"end": 16,
"name": "courseSchema"
},
"init": {
"type": "NewExpression",
"start": 19,
"end": 42,
"callee": {
"type": "Identifier",
"start": 23,
"end": 29,
"name": "Schema"
},
"arguments": [
{
"type": "ObjectExpression",
"start": 30,
"end": 41,
"properties": [
{
"type": "Property",
"start": 36,
"end": 39,
"method": false,
"shorthand": false,
"computed": false,
"key": {
"type": "Identifier",
"start": 36,
"end": 37,
"name": "a"
},
"value": {
"type": "Literal",
"start": 38,
"end": 39,
"value": 1,
"raw": "1"
},
"kind": "init"
}
]
}
]
}
}
],
"kind": "var"
}
],
"sourceType": "module"
}
说明
- Program上入口
- body就上当前脚本包含的所有解析出来的节点
对我们而言,下面这段就够了,其实就上new Schema里的对象内容。具体的在arguments里。
"init": {
"type": "NewExpression",
"start": 19,
"end": 42,
"callee": {
"type": "Identifier",
"start": 23,
"end": 29,
"name": "Schema"
},
"arguments": [
{
"type": "ObjectExpression",
"start": 30,
"end": 41,
"properties": [
{
"type": "Property",
"start": 36,
"end": 39,
"method": false,
"shorthand": false,
"computed": false,
"key": {
"type": "Identifier",
"start": 36,
"end": 37,
"name": "a"
},
"value": {
"type": "Literal",
"start": 38,
"end": 39,
"value": 1,
"raw": "1"
},
"kind": "init"
}
]
}
如果你要是再仔细观察的话,arguments.properties是ObjectExpression表达式。每个属性都是有key的。
对于一般的模型操作来说,一般不会定义很多对象,否则这个model就太难看了。
const acorn = require("acorn")
const walk = require("acorn/dist/walk")
const c = `
var courseSchema = new Schema({
a: 1,
b: 2
})
`
walk.full(acorn.parse(c),node => {
if (node.key) {
console.dir(node.key.name)
console.dir(node.value.value)
}
})
输出结果
$ node test.js
'a'
1
'b'
2
其他的自己玩吧!
1 回复
acorn的代码也是非常有意思的,搭配编译原理龙书和https://github.com/thejameskyle/the-super-tiny-compiler阅读是非常好的