如何在Monaco编辑器中获取hover位置对应的JSON Schema路径?
Monaco编辑器自定义JSON Hover:获取对应Schema路径的方案
一、直接利用Monaco内置JSON语言服务实现
Monaco的JSON语言服务本身已存储JSON节点与Schema的关联信息,无需额外依赖即可完成需求:
定位Hover对应的JSON AST节点
通过编辑器模型和Hover位置,解析出目标JSON节点:const editor = monaco.editor.getEditorById('your-editor-id'); const model = editor.getModel(); const hoverPosition = editor.getPosition(); // 或从hover事件参数中获取position const offset = model.getOffsetAt(hoverPosition); // 获取JSON语言服务实例 const jsonService = monaco.languages.json.JSONLanguageService.getService(); // 解析JSON内容生成AST文档 const jsonDoc = jsonService.parseJSON(model.getValue()); // 根据偏移量找到对应的AST节点 const targetNode = jsonDoc.getNodeFromOffset(offset);匹配对应的Schema片段
利用AST节点的path属性(数组格式,如["user", "age"]),结合自定义Schema遍历定位:const yourSchema = /* 你的自定义JSON Schema对象 */; let currentSchemaPart = yourSchema; // 按节点路径遍历Schema for (const segment of targetNode.path) { if (currentSchemaPart.properties?.[segment]) { currentSchemaPart = currentSchemaPart.properties[segment]; } else if (currentSchemaPart.items && typeof segment === 'number') { currentSchemaPart = currentSchemaPart.items; } // 可根据Schema结构扩展oneOf、anyOf等特殊场景的处理逻辑 } // currentSchemaPart即为Hover位置对应的Schema片段也可以直接调用语言服务的
getHoverContent方法,从返回结果中提取Schema相关信息,省去手动遍历的步骤:const hoverContent = await jsonService.getHoverContent(model, hoverPosition); // hoverContent.contents包含Schema描述等信息,可解析提取对应路径或片段
二、第三方库通用方案(脱离Monaco依赖)
如果需要更灵活的实现,或不想依赖Monaco内部API,可采用以下工具组合:
json-source-map:处理JSON字符串的位置映射,解决空白字符导致的位置偏移问题,精准定位Hover位置对应的JSON节点路径json-schema-traverse:遍历JSON Schema,根据节点路径快速匹配对应的Schema片段
实现步骤:
安装依赖
npm install json-source-map json-schema-traverse定位JSON节点路径
用json-source-map解析JSON内容,匹配Hover位置对应的节点路径:import { parse } from 'json-source-map'; const jsonContent = model.getValue(); // 从Monaco模型获取JSON内容 const hoverPosition = editor.getPosition(); // 解析JSON生成位置映射表 const { pointers } = parse(jsonContent); let targetPath = null; // 遍历所有节点指针,找到匹配Hover位置的节点 for (const [pathStr, info] of Object.entries(pointers)) { const { key, value } = info; // 检查Hover位置是否在节点的key或value范围内 const inKeyArea = key && hoverPosition.lineNumber === key.line + 1 && hoverPosition.column >= key.column && hoverPosition.column <= key.column + key.length; const inValueArea = value && hoverPosition.lineNumber === value.line + 1 && hoverPosition.column >= value.column && hoverPosition.column <= value.column + value.length; if (inKeyArea || inValueArea) { // 将路径字符串转为数组格式(如"/user/age"转为["user", "age"]) targetPath = pathStr.split('/').filter(Boolean); break; } }遍历Schema匹配对应片段
用json-schema-traverse根据节点路径定位Schema:import traverse from 'json-schema-traverse'; const yourSchema = /* 你的自定义JSON Schema对象 */; let targetSchemaPart = yourSchema; traverse(yourSchema, { cb: (schema, jsonPath) => { // 匹配当前Schema路径与目标节点路径 if (JSON.stringify(jsonPath) === JSON.stringify(targetPath)) { targetSchemaPart = schema; } } }); // targetSchemaPart即为Hover位置对应的Schema片段
内容的提问来源于stack exchange,提问作者mwag
相关产品推荐
相关产品推荐

