You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:35:16