基于JSON Schema的JSON智能提示_VSCode插件开发笔记6

一.JSON 智能提示

VS Code 能够对 JSON 进行提示和校验:

在编辑冗长的配置文件时尤为好用,默认支持package.jsontsconfig.json等常见的 JSON 配置

而对于自定义的特殊 JSON 协议,则需要通过 JSON Schema 来扩展支持

二.JSON Schema

要想对 JSON 进行智能提示(或校验),先要有一份元数据,将 JSON 的结构、字段取值和含义等元信息定义清楚

在 VS Code 里,这份元数据用 JSON Schema 来描述:

To understand the structure of JSON files, we use JSON schemas. JSON schemas describe the shape of the JSON file, as well as value sets, default values, and descriptions.

P.S.VS Code 支持目前(2020/5/16)最新的JSON Schema Draft 7 规范

至于 JSON Schema,也是一种基于 JSON 的数据格式,用来定义 JSON 数据的结构

JSON Schema specifies a JSON-based format to define the structure of JSON data for validation, documentation, and interaction control.

(摘自JSON Schema

例如person.json

{
  "first_name": "George",
  "last_name": "Washington",
  "birthday": "1732-02-22",
  "address": {
    "street_address": "3200 Mount Vernon Memorial Highway",
    "city": "Mount Vernon",
    "state": "Virginia",
    "country": "United States"
  }
}

对应的 JSON Schema 为(person.schema.json):

{
  "type": "object",
  "properties": {
    "first_name": { "type": "string" },
    "last_name": { "type": "string" },
    "birthday": { "type": "string", "format": "date" },
    "address": {
      "type": "object",
      "properties": {
        "street_address": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "country": { "type" : "string" }
      }
    }
  }
}

上例看起来像是 JSON 的类型声明,实际上,除类型外还能携带字段取值、含义描述等信息:

{
  "type": "string",
  "pattern": "^(\\([0-9]{3}\\))?[0-9]{3}-[0-9]{4}$",
  "title": "telephone number",
  "description": "a simple North American telephone number with an optional area code"
}

P.S.关于 JSON Schema 的详细信息,见Understanding JSON Schema

三.扩展自定义 JSON 提示

既然 VS Code 提供的 JSON 提示能力是基于 JSON Schema 的,那么要支持自定义的 JSON 格式就相当容易了:

  1. 先创建(手动编写或转换生成)一份 JSON Schema,准备好提示/校验所需的元数据

  2. 再与目标 JSON 文件建立关联,让 VS Code 在打开特定的 JSON 文件时能够找到对应的提示信息(JSON Schema)

生成 JSON Schema

对于简单的、不频繁更新的 JSON 数据,手动编写 JSON Schema 即可,而另一些复杂冗长、时不时扩展几个字段的 JSON 数据,通过工具转换生成通常是更好的选择:

  • JSON 转 JSON Schema:推荐JSON Schema Tool(不开源,但集转换、编辑于一体,功能相对完整,并且支持 draft-07 规范),或者to-json-schema(开源,仅支持转换,配合其它 JSON Schema 编辑器使用)

  • 编辑 JSON Schema:推荐JSON-Schema-Editor可视化编辑器

  • JSON Schema 语法校验:JSON Schema Validator

正确生成 JSON Schema 之后,在 VS Code 中与 JSON 文件建立关联即可

与 JSON 文件建立关联

有 3 种方式建立 JSON Schema 与 JSON 文件的关联:

  • 用户侧:通过用户设置(Settings)中的json.schemas选项来配置映射关系

  • 数据侧:在 JSON 数据中增加一个$schema字段,指向 JSON Schema

  • 第三方:通过jsonValidation扩展点配置映射关系

json.schemas

"json.schemas": [
  {
    "fileMatch": [
      "/.babelrc"
    ],
    "url": "http://json.schemastore.org/babelrc"
  }
]

P.S.JSON Schema Store提供了 200 多个常见配置文件对应的 JSON Schema

表示对所有名为.babelrc的 JSON 文件应用url指向的 JSON Schema,其中url也可以是本地文件的相对路径,例如"url": "./myschema.json"表示当前工作空间根目录下的myschema.json

或者直接将 JSON Schema 写进来:

"json.schemas": [
  {
    "fileMatch": [
      "/.myconfig"
    ],
    "schema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the entry"
        }
      }
    }
  }
]

用户设置操作简单,且不影响 JSON 数据,但缺点在于本地设置不共享,每个人都要配一遍,不适用于多人协作的场景,并且有些特殊场景无法通过fileMatch规则来描述映射关系,此时可以考虑$schema

P.S.注意,如果 JSON 数据文件后缀名不为.json,还需要配置files.association表明此类文件内容按 JSON 处理(因为 JSON Schema 配置仅对 JSON 生效):

"files.associations": {
  ".babelrc": "json"
}

具体见Adding a file extension to a language

$schema

{
  "$schema": "http://json.schemastore.org/coffeelint",
  "line_endings": "unix"
}

由 JSON 数据(通过特殊的$schema字段)附带上对应的 JSON Schema,缺点是会弄脏 JSON 数据,所有消费者都要对$schema做特殊处理,而且不适用于数据侧不受控的情况,比如 JSON 数据是由第三方提供的,要加字段几乎不可能

优势在于能够建立一对一的精确映射,从而满足一些通过映射规则难以描述的场景,比如自定义的 JSON 数据也叫package.json,甚至 JSON 文件名都不固定的情况(具体见support setting schema associations at runtime,将来可能会提供更灵活、不侵入原始数据的 JSON Schema 关联方式)

jsonValidation

{
  "contributes": {
    "jsonValidation": [
      {
        "fileMatch": ".jshintrc",
        "url": "http://json.schemastore.org/jshintrc"
      }
    ]
  }
}

json.schemas用户设置类似,只是将映射关系放到了插件的package.json里集中提供,以解决配置共享的问题,映射关系描述能力的缺陷仍然存在

P.S.jsonValidation仅支持url形式引入 JSON Schema,不支持通过schema直接写进来

四.自动补全

JSON Schema 规范中的default字段可用于 JSON 自动补全(VS Code 默认支持),能够满足一般情况。对于更复杂的补全提示,可通过扩展字段defaultSnippets来完成:

{
  "type": "array",
  "title": "Keybindings configuration",
  "items": {
    "type": "object",
    "required": ["key"],
    "defaultSnippets": [
      {
        "label": "New keybinding",
        "description": "Binds a key to a command for a given state",
        "body": { "key": "$1", "command": "$2", "when": "$3" }
      }
    ],
    "properties": {
      "key": {
        "type": "string"
      }
    }
  }
}

defaultSnippets中的body语法与Snippets相同,支持控制光标位置,使用占位符、预定义的常量(当前文件名、年月日等)等

P.S.defaultSnippets不属于 JSON Schema 规范的一部分,而是 VS Code 为了增强 JSON 的补全能力扩展出的自定义字段(JSON Schema 规范允许扩展,忽略所有未知字段)

参考资料

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code