使用acorn语法解析器来获取model里的key
发布于 1 个月前 作者 i5ting 348 次浏览 来自 分享

获取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阅读是非常好的

回到顶部