目录

1.集成jsoneditor到React

2.修改代码

(1).添加Option

(2).修改Node.js文件

(3).修改util.js文件

3.扩展:


1.集成jsoneditor到React

关于怎样将jsoneditor集成到React中,请参考文章:https://blog.csdn.net/wdquan19851029/article/details/115869264,本文只讲怎样修改jsoneditor源码,使用password格式保护json敏感信息。

从github下载源代码:https://github.com/josdejong/jsoneditor

2.修改代码

我们得考虑,真正使用的时候,我们一般只是需要保护部分敏感信息,没有必要保护所有信息,那样根本什么信息都看不到,所以我们只考虑保护部分信息。

看我们的json数据,其中有需要保护的数据 "sensitive-data".

        const initialJson = {
            "Array": [1, 2, 3],
            "Boolean": true,
            "Null": null,
            "Number": 123,
            "Object": {"a": "b", "c": "d"},
            "MultiLevel":{
                "multi":{
                    "e": "f",
                    "h": "h"
                }
            },
            "String": "Hello World",
            "sensitive-data": {
                "sensitive1": "sensitive1",
                "sensitive2": "sensitive2",
                "sensitive3": "sensitive3"
            }
        }

(1).添加Option

需要保护的信息,我们设计以option的形式传进去。我们自己添加一个新的参数sensitiveDataLabel ,设置其值为"sensitive-data"

        const options = {
            mode: 'tree',
            sensitiveDataLabel: 'sensitive-data',
            onChangeJSON: (data)=>{
                console.log('JSONeditor:change:',data);}
        }

(2).修改Node.js文件

然后修改Node.js的_createDomValue ()函数:其中注释为"新增的代码",是我做的修改,主要是判断parent node的name是不是与我们传进来的option sensitiveDataLabel 相等,如果相等,那么就创建一个input标签,type为password,用来保护敏感信息。

  /**
   * Create an editable value
   * @private
   */
  _createDomValue () {
    let domValue

    if (this.type === 'array') {
      domValue = document.createElement('div')
      domValue.textContent = '[...]'
    } else if (this.type === 'object') {
      domValue = document.createElement('div')
      domValue.textContent = '{...}'
    } else {
      if (!this.editable.value && isUrl(this.value)) {
        // create a link in case of read-only editor and value containing an url
        domValue = document.createElement('a')
        domValue.href = this.value
        domValue.innerHTML = this._escapeHTML(this.value)
      } else {
        // create an editable or read-only div
        //新增的代码
        let isSensitiveData = false
        //判断是否敏感数据方式1,只看当前node的parent,这是不合适的,因为可能有嵌套
        //if(this.parent) {
          //let sensitiveDataLabel = ""
          //if(this.editor.options.sensitiveDataLabel) sensitiveDataLabel = this.editor.options.sensitiveDataLabel
          //if(this.parent.getName() && this.parent.getName() == sensitiveDataLabel){
            //isSensitiveData = true
          //}
        //}
        //判断是否敏感数据方式2,因为敏感数据也有可能嵌套,所以不能只看当前node的parent,而要看其所有的json路径
        let nodePaths = this.getNodePath()
        let sensitiveDataLabel = ""
        if(this.editor.options.sensitiveDataLabel) sensitiveDataLabel = this.editor.options.sensitiveDataLabel
        for(var i = 0; i < nodePaths.length; i++) {
          if(nodePaths[i].field && nodePaths[i].field == sensitiveDataLabel){
            isSensitiveData = true
            break;
          }
        }
        if(isSensitiveData){
          //新增的代码
          domValue = document.createElement('input')
          domValue.type = "password"
          domValue.placeholder=""
          domValue.autocomplete = "new-password" //防止自动填充保存过的登录密码
          domValue.style.border = "none" //去掉输入框的边框
          domValue.contentEditable = this.editable.value
          domValue.spellcheck = false
          domValue.value = this._escapeHTML(this.value)
        }else{
          domValue = document.createElement('div')
          domValue.contentEditable = this.editable.value
          domValue.spellcheck = false
          domValue.innerHTML = this._escapeHTML(this.value)
        }
      }
    }

    return domValue
  }

重新编译源代码,并导入React工程之后,可以看到效果:

(3).修改util.js文件

但是当进行修改的时候,发现修改无效,头疼,继续修改代码,修改util.js文件中的getInnerText (element, buffer)函数。

注释为"新增的代码"部分,就是我做的修改,将用户在上面界面的修改,赋给child这个Node,因为以前都是用<div>标签去显示value,现在改成了<input>,按照以前的方式,是用innerHTML属性获取值,但是现在需要使用value属性去获取值。

export function getInnerText (element, buffer) {
  const first = (buffer === undefined)
  if (first) {
    buffer = {
      _text: '',
      flush: function () {
        const text = this._text
        this._text = ''
        return text
      },
      set: function (text) {
        this._text = text
      }
    }
  }

  // text node
  //console.log("Debug: getInnerText() -> element.nodeValue : " + element.nodeValue)
  if (element.nodeValue) {
    // remove return characters and the whitespace surrounding return characters
    const trimmedValue = element.nodeValue.replace(/\s*\n\s*/g, '')
    if (trimmedValue !== '') {
      return buffer.flush() + trimmedValue
    } else {
      // ignore empty text
      return ''
    }
  }

  // divs or other HTML elements
  if (element.hasChildNodes()) {
    const childNodes = element.childNodes
    let innerText = ''

    for (let i = 0, iMax = childNodes.length; i < iMax; i++) {
      const child = childNodes[i]

      //新增的代码
      if(element.type == "password" && element.value){
        child.nodeValue = element.value;
      }

      if (child.nodeName === 'DIV' || child.nodeName === 'P') {
        const prevChild = childNodes[i - 1]
        const prevName = prevChild ? prevChild.nodeName : undefined
        if (prevName && prevName !== 'DIV' && prevName !== 'P' && prevName !== 'BR') {
          if (innerText !== '') {
            innerText += '\n'
          }
          buffer.flush()
        }
        innerText += getInnerText(child, buffer)
        buffer.set('\n')
      } else if (child.nodeName === 'BR') {
        innerText += buffer.flush()
        buffer.set('\n')
      } else {
        innerText += getInnerText(child, buffer)
      }
    }

    return innerText
  }

  // br or unknown
  return ''
}

3.扩展:

如果除了"sensitive-data"数据,还有别的数据需要保护,怎么办? 其实非常简单,传参数的时候,传入一个数组 sensitiveDataLabel: ['sensitive-data', 'sensitive-data1', 'sensitive-data2'],然后在Node.js中判断的时候,将if(nodePaths[i].field && nodePaths[i].field == sensitiveDataLabel) 改为if(nodePaths[i].field && sensitiveDataLabel.indexOf(nodePaths[i].field) > -1),大体就是这样子,有需要的话,请自己进行修改。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐