亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何通過遞歸方法實現(xiàn)用json-diff渲染json字符串對比結(jié)果

 更新時間:2022年12月06日 09:37:43   作者:鄭丫頭  
JsonDiff是一個高性能json差異發(fā)現(xiàn)工具,它幾乎可以發(fā)現(xiàn)任何JSON結(jié)構(gòu)的差異,并且將錯誤信息反饋給用戶,下面這篇文章主要給大家介紹了關(guān)于如何通過遞歸方法實現(xiàn)用json-diff渲染json字符串對比結(jié)果的相關(guān)資料,需要的朋友可以參考下

前言

上一篇,對比了js-diff和json-diff,發(fā)現(xiàn)js-diff對比的結(jié)果返回的是拆分后字符串并且字符串中帶有換行符跟空格,將拆分后的字符串拼接可以得到完整的兩個json格式化后的信息。但是json-diff只返回了兩個json中有修改的的部分,并且返回類型還要根據(jù)值類型來進行判斷。

分析json-diff的結(jié)構(gòu)

用兩個數(shù)組嵌套對象,對象嵌套數(shù)組的比較復(fù)雜的json進行對比,獲得的數(shù)據(jù)如下:

var json1 = {
  name: '小明',
  age: '22',
  hobby: ['籃球', '足球', '羽毛球'],
  grade: {
    English: ['130', '129', '135'],
    Chinese: ['120', '118', '122'],
    sports: ['90', '90', '90'],
  },
  honor: [{ desc: '獲得數(shù)學(xué)競賽第一名', info: [{ score: '100', ranking: 1 }, 2, 3] }],
}
var json2 = {
  name: '小紅',
  age: '22',
  hobby: ['乒乓球', '羽毛球'],
  grade: {
    English: ['120', '129', '125'],
    Chinese: ['140', '139', '136'],
    sports: ['90', '90', '90'],
  },
  honor: [{ desc: '獲得作文比賽第一名', info: [{ score: '99', rank: 2 }, 2, 3] }],
}
var jsonDiff = {
    "name": {
        "__old": "小明",
        "__new": "小紅"
    },
    "hobby": [
        [
            "-",
            "籃球"
        ],
        [
            "-",
            "足球"
        ],
        [
            "+",
            "乒乓球"
        ],
        [
            " "
        ]
    ],
    "grade": {
        "English": [
            [
                "-",
                "130"
            ],
            [
                "+",
                "120"
            ],
            [
                " "
            ],
            [
                "-",
                "135"
            ],
            [
                "+",
                "125"
            ]
        ],
        "Chinese": [
            [
                "-",
                "120"
            ],
            [
                "-",
                "118"
            ],
            [
                "-",
                "122"
            ],
            [
                "+",
                "140"
            ],
            [
                "+",
                "139"
            ],
            [
                "+",
                "136"
            ]
        ]
    },
    "honor": [
        [
            "~",
            {
                "desc": {
                    "__old": "獲得數(shù)學(xué)競賽第一名",
                    "__new": "獲得作文比賽第一名"
                },
                "info": [
                    [
                        "~",
                        {
                            "ranking__deleted": 1,
                            "rank__added": 2,
                            "score": {
                                "__old": "100",
                                "__new": "99"
                            }
                        }
                    ],
                    [
                        " "
                    ],
                    [
                        " "
                    ]
                ]
            }
        ]
    ]
};

可以觀察到:

  • 字符串返回{"__old":string,"__new":string},數(shù)組返回[string[,string][,object]],非數(shù)組對象返回{ "key__added": string|object, "key__deleted": string|object, "key": string|object }。
  • 字符串通過__old、__new獲取
  • 非數(shù)組對象新增屬性從key__added獲取,刪除屬性從key__deleted獲取
  • 數(shù)組第一個值有四種類型空格表示未修改、+表示新增、-表示刪除、~表示修改

解析結(jié)構(gòu)圖如下:

太繞了,畫圖之后才看的明白一點ORZ...

用遞歸方法拼接json字符串

首先創(chuàng)建一個函數(shù)用來判斷json是否為數(shù)組,renderobj(diffObj, originObj, n),diffObj表示當(dāng)層的diff對象,originObj表示當(dāng)層的json1對象,n表示深度,第一層深度為0,主要為了方便計算縮進。

renderobj函數(shù):

// 定義remove和add隊列
const removeList = [];
const addlist = [];
if (diffObj instanceof Array) {
    // 數(shù)組的判斷
} else if (typeof diffObj == 'object'){
    if (diffObj.__new) {
        // 字符串修改
    } else {
        // 非數(shù)組對象修改
    }
}

字符串修改

當(dāng)diffObj.__new為真時,__old同時有值,表示字符串做修改,此時可以直接把__new放到addList,__old存入removeList。

addlist.push(`<span style="color:red;">"${diffObj.__new}"</span>,<br/>`);
removeList.push(`<span style="color:red;">"${diffObj.__old}"</span>,<br/>`);

非數(shù)組對象修改

const { addHtml, removeHtml } = renderObject(diffObj, originObj, n);
addlist.push(addHtml);
removeList.push(removeHtml);

非數(shù)組對象要判斷key的值,創(chuàng)建函數(shù)renderObject(diffObj, originObj, n),傳參同renderobj。

const addlist = [];
const removeList = [];
addlist.push(`{</br>`);
removeList.push(`{</br>`);

// 遍歷originObj,遍歷diffObj...

addlist.push(`${spaceStr.repeat(n)}},</br>`);
removeList.push(`${spaceStr.repeat(n)}},</br>`);
return {
  addHtml: addlist.join(''),
  removeHtml: removeList.join(''),
};

為啥要分別遍歷originObj和diffObj?因為json1對象中沒有新增的key,diffObj中沒有返回未修改key。

const spaceStr = '    ';
Object.keys(originObj).forEach(key => {
  const keyVal = diffObj[key];
  if (keyVal) {
   // renderobj重新判斷修改類型
    const { addHtml, removeHtml } = renderobj(keyVal, originObj[key], n + 1);
    if (keyVal.__new) {
      // 當(dāng)字符串修改時,將整行標(biāo)紅
      addlist.push('<div class="error-line-add">');
      removeList.push('<div class="error-line-remove">');
    }
    addlist.push(`${spaceStr.repeat(n + 1)}"${key}": ${addHtml}`);
    removeList.push(`${spaceStr.repeat(n + 1)}"${key}": ${removeHtml}`);
    if (keyVal.__new) {
      addlist.push(`</div>`);
      removeList.push(`</div>`);
    }
  } else {
    const remove = diffObj[key + '__deleted'];
    if (remove) {
      // 刪除的屬性
      removeList.push('<div class="error-line-remove">');
      removeList.push(
        `<span style="color:red;">${spaceStr.repeat(n + 1)}"${key}": ${renderJson(
          remove,
          n + 1
        )}</span></br>`
      );
      removeList.push('</div>');
    } else {
      // 沒修改的屬性直接存入
      addlist.push(
        `${spaceStr.repeat(n + 1)}"${key}": ${renderJson(originObj[key], n + 1)}</br>`
      );
      removeList.push(
        `${spaceStr.repeat(n + 1)}"${key}": ${renderJson(originObj[key], n + 1)}</br>`
      );
    }
  }
})
Object.keys(diffObj).forEach(key => {
  // 新增的屬性,json1中沒有,從diffObj中遍歷
  if (key.includes('__added')) {
    addlist.push('<div class="error-line-add">');
    addlist.push(
      `<span style="color: red;">${spaceStr.repeat(n + 1)}"${key.replace('__added', '')}": "${diffObj[key]}",</br></span>`
    );
    addlist.push('</div>');
  }
});

數(shù)組對象修改

遍歷diffObj,判斷item[0]的值,當(dāng)值為空格時,需要從json1中獲取原屬性值,diffObj中空格所在的索引位置有可能和originObj中索引的位置不同,要排除掉'+'新增的成員;當(dāng)值為'+'時,直接將值存入addList;當(dāng)值為'-'時,直接將值存入removeList;當(dāng)值為'~'時,表示有修改,修改類型不確定需要重新循環(huán)判斷。

addlist.push(`[</br>`);
removeList.push(`[</br>`);
diffObj.forEach((item, i) => {
    switch (item[0]) {
      case '~': {
        // 有修改,重新判斷修改的值的類型
        const { addHtml, removeHtml } = renderobj(item[1], originObj[i], n + 1);
        addlist.push(`${spaceStr.repeat(n + 1)}${addHtml}`);
        removeList.push(`${spaceStr.repeat(n + 1)}${removeHtml}`);
        break;
      }
      case '-': {
        // 刪除屬性
        removeList.push('<div class="error-line-remove">');
        removeList.push(
          `<span style="color: red;">${spaceStr.repeat(n + 1)}${renderJson(
            item[1],
            n + 1
          )}</br>`
        );
        removeList.push('</div>');
        break;
      }
      case '+': {
        // 新增屬性
        addlist.push('<div class="error-line-add">');
        addlist.push(
          `<span style="color: red;">${spaceStr.repeat(n + 1)}${renderJson(
            item[1],
            n + 1
          )}</br>`
        );
        addlist.push('</div>');
        break;
      }
      case ' ': {
        // 屬性未修改,從originObj中獲取,注意對應(yīng)的index不包括新增的屬性
        const index = diffObj.slice(0, i).filter(item => item[0] != '+').length;
        const value = originObj[index];
        const itemStr = `${spaceStr.repeat(n + 1)}${renderJson(value, n + 1)}</br>`;
        addlist.push(itemStr);
        removeList.push(itemStr);
        break;
      }
    }
});
addlist.push(`${spaceStr.repeat(n)}],</br>`);
removeList.push(`${spaceStr.repeat(n)}],</br>`);

renderJson函數(shù),用來格式化json值:

const renderJson = (json, n) => {
  if (!json) {
    return "";
  }
  if (typeof json == "string" || typeof json == "number") {
    return `"${json}",`;
  }
  return `${JSON.stringify(json, null, "\t")
    .replace(new RegExp("\n", "g"), `</br>${spaceStr.repeat(n)}`)
    .replace(new RegExp("\t", "g"), spaceStr.repeat(n))},`;
};

最后對比顯示結(jié)果如下:

總結(jié)

到此這篇關(guān)于如何通過遞歸方法實現(xiàn)用json-diff渲染json字符串對比結(jié)果的文章就介紹到這了,更多相關(guān)json-diff渲染json字符串對比結(jié)果內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Electron應(yīng)用顯示隱藏時展示動畫效果實例

    Electron應(yīng)用顯示隱藏時展示動畫效果實例

    最近使用electron實現(xiàn)一個簡單的功能,下面這篇文章主要給大家介紹了關(guān)于Electron應(yīng)用顯示隱藏時展示動畫效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • Bootstrap DateTime Picker日歷控件簡單應(yīng)用

    Bootstrap DateTime Picker日歷控件簡單應(yīng)用

    這篇文章主要介紹了Bootstrap DateTime Picker日歷控件的簡單應(yīng)用,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 用JS實現(xiàn)3D球狀標(biāo)簽云示例代碼

    用JS實現(xiàn)3D球狀標(biāo)簽云示例代碼

    3D球狀標(biāo)簽云的效果想必很多朋友在瀏覽網(wǎng)頁時都有見到過吧,看起來提復(fù)雜的,其實實現(xiàn)起來挺容易的,感興趣的朋友可以了解下本文
    2013-12-12
  • 微信小程序ajax實現(xiàn)請求服務(wù)器數(shù)據(jù)及模版遍歷數(shù)據(jù)功能示例

    微信小程序ajax實現(xiàn)請求服務(wù)器數(shù)據(jù)及模版遍歷數(shù)據(jù)功能示例

    這篇文章主要介紹了微信小程序ajax實現(xiàn)請求服務(wù)器數(shù)據(jù)及模版遍歷數(shù)據(jù)功能,結(jié)合實例形式分析了微信小程序ajax調(diào)用及模板wx:for循環(huán)列表渲染相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • JavaScript中textRange對象使用方法小結(jié)

    JavaScript中textRange對象使用方法小結(jié)

    這篇文章主要介紹了JavaScript中textRange對象使用方法小結(jié),需要的朋友可以參考下
    2015-03-03
  • layui中的switch開關(guān)實現(xiàn)方法

    layui中的switch開關(guān)實現(xiàn)方法

    今天小編就為大家分享一篇layui中的switch開關(guān)實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • js 一個關(guān)于圖片onload加載的事

    js 一個關(guān)于圖片onload加載的事

    前幾天一個項目讓我頭疼了很久,一個關(guān)于圖片加載時的loading效果,因為不是太懂js,所以在網(wǎng)上各種找資料,但還是不理想,無賴苦心研究,終于有了一點眉目了,雖然個中還有一些道理不懂,至少目的達到了
    2013-11-11
  • GoJs中的動畫使用示例詳解

    GoJs中的動畫使用示例詳解

    這篇文章主要為大家介紹了GoJs中的動畫使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 聊一聊JS中的prototype

    聊一聊JS中的prototype

    function定義的對象有一個prototype屬性,prototype屬性又指向了一個prototype對象,注意prototype屬性與prototype對象是兩個不同的東西,要注意區(qū)別.這篇文章主要介紹了JS中的prototype的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • JavaScript 實現(xiàn)鼠標(biāo)拖動元素實例代碼

    JavaScript 實現(xiàn)鼠標(biāo)拖動元素實例代碼

    這篇文章主要介紹了JavaScript 實現(xiàn)鼠標(biāo)拖動元素實例代碼,需要的朋友可以參考下
    2014-02-02

最新評論