將 JSON 數據格式輸出至頁面上

JSON 是一種輕量級的數據交換格式,它有鍵值對集合(js 中的對象)和數組兩種結構。JSON是一個通用的格式,在先後端語言中都能跟該 JSON 打交道。css

有時候咱們須要將 JSON 格式輸入至頁面展現的需求,其中還須要保持必定的索引,那麼該如何實現呢?html

使用

咱們將對象轉爲 JSON 字符串時會常常使用 JSON.stringify 這個 API,其實該方法就內置有格式化的參數:git

var userInfo = {name: 'anran758',github: 'https://github.com/anran758'};
var info = JSON.stringify(userInfo, null, 2);

console.log(info);
// "{↵  "name": "anran758",↵  "github": "https://github.com/anran758"↵}"

在上面的代碼中,咱們第一個參數(value)傳入了一個須要序列化的對象。第二個參數是replacer,用以對屬性轉換和處理,因爲咱們不須要額外的處理,所以傳入一個null;第三個參數則是空格索引的個數,封頂是100或不傳則沒有空格。github

在控制檯打印出信息後,咱們能夠看的出來格式化的數據是帶換行符,而且有縮進的格式。接下來咱們就要考慮如何輸出到頁面中。面試

輸出

只要學過HTML的朋友都知道,咱們直接將數據輸入至HTML中,空格縮進會被瀏覽器給忽略掉的。所以不能輸入到<div>中。這時候又想到,JSON格式實際上也算是代碼的一種,那能不能輸入至雷士代碼塊的標籤中呢?答案是能夠的。後端

HTML 中有兩個標籤能夠展現源代碼: <pre><code> 。它們之間不一樣之處在於:數組

  • <pre> 表示預約義格式文本,按照原文件中的編排,以等寬字體的形式展示出來,文本中的空白符(好比空格和換行符)都會顯示出來
  • <code> 則是呈現一段計算機代碼,它以瀏覽器的默認等寬字體顯示,但並不必定會完整呈現原來的格式

這些標籤知識實際上算是比較冷門的知識,或許遠古的面試題會考這種知識點,平時不多會遇到。可是若是你常常使用markdown的話,那麼這些標籤在markdown中有不一樣的別名:瀏覽器

好比 markdown 語法中的 ``,實際上等同於 <code> 標籤。實際做用是短代碼塊標籤

而 markdown 語法中的長代碼塊就等同於 <pre> 標籤,不一樣的博客或者網站的應用中還能夠對 <pre> 加類名,用以展現不一樣的語言的語法高亮。

經過三者之間的對比能夠看出,只有 <pre> 纔是符合咱們需求的。markdown

代碼格式輸出 - demo1dom

肯定好展現的方式後,就能夠考慮進一步擴展格式化的功能。好比對象中還有屬性是 JSON 字符串的話,咱也進一步的解析,直至最底層。想實現這種功能須要編寫一個遞歸函數,考慮以下代碼:

const isPlainObject = (v) => Object.prototype.toString.call(v) === "[object Object]"
const isString = (v) => Object.prototype.toString.call(v) === "[object String]"

/**
 * 格式 JSON 字符串爲對象
 *
 * @author anran758
 * @param { any }
 */
function formatJsonStrAsObj(sample) {
  let temp = sample;

  if (isString(temp)) {
    // 由於有解析失敗的可能,使用 try catch 作相應處理
    try {
      temp = JSON.parse(temp);
    } catch (ex) {
      // parse error,return this sample
      return sample;
    }
  }

  if (isPlainObject(temp)) {
    temp = { ...temp };

    Object.keys(temp).forEach(key => {
      const item = temp[key];

      // 字符串或者對象進行遞歸確認
      if (isString(item) || isPlainObject(item)) {
        temp[key] = formatJsonStrAsObj(item);
      }
    });
  }

  return temp;
}

/**
 * 將 JSON 字符串轉換爲帶縮進的字符串
 *
 * @param {*} sample JSON 字符串
 * @param {number} [indnt=2] 縮進數
 * @returns
 */
function formatJSONIndnt(sample, indnt = 2) {
  const newSample = formatJsonStrAsObj(sample);

  if (isString(newSample)) return newSample;

  try {
    return JSON.stringify(newSample, null, indnt);
  } catch (ex) {
    return newSample.toString();
  }
}

const info = JSON.stringify({
  name: 'anran758',
  avatar: 'https://xxx',
  detail: JSON.stringify({
    desc: 'some description',
    level: 2,
  })
})
const data = formatJSONIndnt(info);
console.log(data);

// 能夠直接將 data 輸出至 dom 中

輸入

上文講了如何將數據輸出至頁面,以及擴展格式化功能的示例。接下來說解輸入方面的應用。

當用戶從別的地方複製數據想粘貼至輸入框時,能夠在輸入框上設置監控事件,觸發事件後嘗試幫用戶格式化數據,示例代碼以下:

<div class="container">
  <pre class="preview pre"></pre>
  <textarea class="textarea"></textarea>
</div>
const info = JSON.stringify({
  name: 'anran758',
  avatar: 'https://xxx',
  detail: JSON.stringify({
    desc: 'some description',
    level: 2,
  })
})
const data = formatJSONIndnt(info);

const textarea = document.querySelector('.textarea');
const preview = document.querySelector('.pre');

preview.innerHTML = data;
textarea.addEventListener('paste', (e) => {
  // 阻止默認事件
  e.preventDefault();
  const value = (e.clipboardData || window.clipboardData).getData('text');

  // 這裏使用了上面定義的函數,進行格式化數據
  e.target.value = formatJSONIndnt(value, 2);
})
body {
  display: flex;
  margin: 0;
  justify-content: center;
  align-items: center;
  padding: 0 10px;
  box-sizing: border-box;
  min-height: 100vh;
}

.container {
  display: flex;
  width: 100%;
}

.preview {
  flex: 1;
  margin-bottom: 20px;
  padding: 20px;
  background: #f5fcff;
  border: 1px solid #d3eeff;
  border-radius: 3px;
  margin: 0;
}

.textarea {
  flex: 1;
  margin-left: 20px;
  padding: 10px;
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
    monospace;
}

.preview + .preview {
  margin-left: 10px;
}

代碼格式輸入 - demo1

參考資料

相關文章
相關標籤/搜索