如何在Monaco Editor的JSON语言中设置属性为只读?
在Monaco Editor的JSON中设置属性为只读的方案
Monaco Editor的JSON语言服务本身不支持通过JSON Schema配置readonly属性来锁定字段——不管是在属性定义内加"readonly": true,还是在properties同级配置"readonly": ["p1"]都不行,因为标准JSON Schema没有这个关键字,Monaco的JSON服务也未扩展该功能。你之前用的required是标准JSON Schema的内置关键字,所以能生效,但readonly不属于这个范畴。
下面是两种可行的实现方式:
方式一:用装饰器+编辑拦截实现只读
通过添加装饰器标记只读属性的视觉样式,同时监听编辑器内容变化事件,拦截对目标属性的修改:
// 初始化编辑器 const editor = monaco.editor.create(document.getElementById('container'), { value: JSON.stringify({ p1: "不可修改", p2: "可修改" }, null, 2), language: 'json' }); // 定义需要设为只读的属性名 const readOnlyProperty = "p1"; // 生成只读装饰器的方法 function updateReadOnlyDecorations() { const model = editor.getModel(); if (!model) return; const decorations = []; const text = model.getValue(); // 匹配属性名和对应值的正则 const regex = new RegExp(`"${readOnlyProperty}"\\s*:\\s*"([^"]+)"`, 'g'); let match; while ((match = regex.exec(text)) !== null) { const startPos = model.getPositionAt(match.index); const endPos = model.getPositionAt(match.index + match[0].length); decorations.push({ range: new monaco.Range(startPos.lineNumber, startPos.column, endPos.lineNumber, endPos.column), options: { isWholeLine: false, inlineClassName: 'readonly-property' } }); } // 创建装饰器类型并应用到编辑器 editor.setDecorations(monaco.editor.createDecorationType({ cursor: 'not-allowed', backgroundColor: '#f5f5f5', textDecoration: 'none' }), decorations); } // 初始化装饰器 updateReadOnlyDecorations(); // 监听内容变化,拦截只读属性的修改 editor.onDidChangeContent((event) => { const model = editor.getModel(); if (!model) return; const originalValue = editor.getModel().getValue(); const regex = new RegExp(`"${readOnlyProperty}"\\s*:\\s*"([^"]+)"`, 'g'); // 记录原始属性值 const originalMatch = regex.exec(originalValue); if (!originalMatch) return; // 延迟检查(确保内容已更新) setTimeout(() => { const newValue = model.getValue(); const newMatch = regex.exec(newValue); // 如果属性值被修改,恢复原始内容 if (!newMatch || newMatch[1] !== originalMatch[1]) { model.setValue(originalValue); updateReadOnlyDecorations(); } }, 0); });
可以添加CSS增强视觉提示:
.readonly-property { opacity: 0.8; }
方式二:自定义JSON语言服务(进阶)
如果需要更深度的集成,可以扩展Monaco的JSON语言服务,在代码补全、语法验证阶段阻止对只读属性的修改,但该方案复杂度较高,需要熟悉Monaco的语言服务扩展API,适合有定制化需求的场景。
内容的提问来源于stack exchange,提问作者Farokh Morshed
相关产品推荐
相关产品推荐

