diff options
Diffstat (limited to 'files/zh-tw/learn/javascript/objects/json/index.html')
-rw-r--r-- | files/zh-tw/learn/javascript/objects/json/index.html | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/files/zh-tw/learn/javascript/objects/json/index.html b/files/zh-tw/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..71a4a3776a --- /dev/null +++ b/files/zh-tw/learn/javascript/objects/json/index.html @@ -0,0 +1,325 @@ +--- +title: 使用 JSON 資料 +slug: Learn/JavaScript/Objects/JSON +tags: + - JSON +translation_of: Learn/JavaScript/Objects/JSON +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">JavaScript Object Notation (JSON) 為將結構化資料 (structured data) 呈現為 JavaScript 物件的標準格式,常用於網站上的資料呈現、傳輸 (例如將資料從伺服器送至用戶端,以利顯示網頁)。你應該會常常遇到,因此本文將說明 JavaScript 搭配 JSON 時所應知道的觀念,包含如何在 JSON 物件中存取資料項目,並寫出你自己的 JSON。</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">必要條件:</th> + <td>基礎的計算機素養、了解 HTML 與 CSS 的基本概念、熟悉 JavaScript (參閱〈<a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a>〉與〈<a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>〉) 與 OOJS 基本概念 (參閱〈<a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>〉)。</td> + </tr> + <tr> + <th scope="row">主旨:</th> + <td>了解應如何使用 JSON 格式所儲存的資料,建立自己的 JSON 物件。</td> + </tr> + </tbody> +</table> + +<h2 id="說真的,到底什麼是_JSON?">說真的,到底什麼是 JSON?</h2> + +<p>{{glossary("JSON")}} 是依照 JavaScript 物件語法的資料格式,經 <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Douglas Crockford</a> 推廣普及。雖然 JSON 是以 JavaScript 語法為基礎,但可獨立使用,且許多程式設計環境亦可讀取 (剖析) 並產生 JSON。</p> + +<p>JSON 可能是物件或字串。當你想從 JSON中讀取資料時,JSON可作為物件;當要跨網路傳送 JSON 時,就會是字串。這不是什麼大問題 — JavaScript 提供全域 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> 物件,其內的函式可進行切換。</p> + +<p>JSON 物件可儲存於其自有的檔案中,基本上就是副檔名為 <code>.json</code> 的文字檔案,以及 <code>application/json</code> 的 {{glossary("MIME type")}}。</p> + +<h3 id="JSON_的架構">JSON 的架構</h3> + +<p>我們剛提到「JSON 物件基本上就是 JavaScript 物件」,而這敘述在大多數情況下都對。如同標準的 JavaScript 物件,你當然可在 JSON 之內加入相同的基本資料類型,如字串、數字、陣列、布林值,以及其他物件,接著同樣能再建構出資料繼承,如:</p> + +<pre class="brush: json">{ + "squadName" : "Super hero squad", + "homeTown" : "Metro City", + "formed" : 2016, + "secretBase" : "Super tower", + "active" : true, + "members" : [ + { + "name" : "Molecule Man", + "age" : 29, + "secretIdentity" : "Dan Jukes", + "powers" : [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name" : "Madame Uppercut", + "age" : 39, + "secretIdentity" : "Jane Wilson", + "powers" : [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + }, + { + "name" : "Eternal Flame", + "age" : 1000000, + "secretIdentity" : "Unknown", + "powers" : [ + "Immortality", + "Heat Immunity", + "Inferno", + "Teleportation", + "Interdimensional travel" + ] + } + ] +}</pre> + +<p>舉例來說,如果將此物件載入至 JavaScript 程式並將之儲存為「<code>superHeroes</code>」變數,如同〈<a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript 物件基本概念</a>〉一文中提過的,接著能以相同的 存取其內部的資料,如下:</p> + +<pre class="brush: js">superHeroes.hometown +superHeroes["active"]</pre> + +<p>若要順著繼承往下存取資料,只要將必要的屬性名稱與陣列索引「鍊」在一起即可。舉例來說,如果要存取成員列表中的第二位英雄的第三項超能力,你必須:</p> + +<pre class="brush: js">superHeroes["members"][1]["powers"][2]</pre> + +<ol> + <li>首先要有變數名稱 — <code>superHeroes</code>。</li> + <li>要在變數中存取 <code>members</code> 屬性,所以用 <code>["members"]</code>。</li> + <li><code>members</code> 包含由物件產生陣列。我們要存取陣列中的第二個物件,所以用 <code>[1]</code>。</li> + <li>在此物件中,我們要存取 <code>powers</code> 屬性,所以用 <code>["powers"]</code>。</li> + <li>在 <code>powers</code> 屬性中有 1 個陣列具備所選超級英雄的能力。我們要選第三種能力,所以用 <code>[2]</code>。</li> +</ol> + +<div class="note"> +<p><strong>注意:</strong>我們在 <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONText.html</a> 範例 (參閱<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">原始碼</a>) 的變數中,示範上述可用的 JSON。你可在自己瀏覽器的 JavaScript 主控台載入此程式碼,並存取變數中的資料。</p> +</div> + +<h3 id="陣列作為_JSON">陣列作為 JSON</h3> + +<p>我們在上面提過「 JSON 物件基本上就是 JavaScript 物件,而這敘述在大多數情況下都對」。其中「在大多數情況下都對」的理由,就是因為陣列也可以是有效的 JSON 物件,例如:</p> + +<pre class="brush: json">[ + { + "name" : "Molecule Man", + "age" : 29, + "secretIdentity" : "Dan Jukes", + "powers" : [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name" : "Madame Uppercut", + "age" : 39, + "secretIdentity" : "Jane Wilson", + "powers" : [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + } +]</pre> + +<p>上面程式碼絕對是有效的 JSON。你可用陣列指數為開頭來存取陣列項目,例如 <code>[0]["powers"][0]</code>。</p> + +<h3 id="其他附註">其他附註</h3> + +<ul> + <li>JSON 是純粹的資料格式 — 僅具備屬性,而無函式。</li> + <li>JSON 需要雙引號,才能使用\有效。所以最安全的方法就是以雙引號撰寫之。</li> + <li>單一個逗號或冒號放錯位置,也會讓 JSON 檔案出錯而無法運作。你應仔細檢視所有要使用的資料 (只要產生器程式能正確運作,由電腦產生的 JSON 也就不容易出錯)。你可透過如 <a href="http://jsonlint.com/">JSONLint</a> 的應用程式檢驗 JSON。</li> + <li>不限於陣列或物件,只要是符合標準 JSON 物件形式的任何資料,都可以夾帶進 JSON 檔案中。因此,單一字串或數字也可能是有效的 JSON 物件,但不一定有用就是了...</li> +</ul> + +<h2 id="主動學習:完成_JSON_範例">主動學習:完成 JSON 範例</h2> + +<p>現在就試著在網站上,透過某些 JSON 資料完成範例吧。</p> + +<h3 id="入門">入門</h3> + +<p>在開始之前,先複製我們的 <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> 與 <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a> 到你的本端硬碟中。後者包含某些簡易的 CSS 可塑造網頁風格;前者則提供極簡單主體 HTML:</p> + +<pre class="brush: html"><header> +</header> + +<section> +</section></pre> + +<p>加上 {{HTMLElement("script")}} 元素,才能納入稍後會在此習題中寫出來的 JavaScript 程式碼。目前只有 2 行程式碼,用以取得 {{HTMLElement("header")}} 與 {{HTMLElement("section")}} 元素的參考,並將之儲存於變數之中:</p> + +<pre class="brush: js">var header = document.querySelector('header'); +var section = document.querySelector('section');</pre> + +<p>你可到 GitHub 上找到此 JSON 資料:<a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>。</p> + +<p>接著載入到頁面之中,並使用某些有趣的 DOM 操控 (DOM manipulation) 來顯示,如下:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13857/json-superheroes.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="載入我們的_JSON">載入我們的 JSON</h3> + +<p>若要將 JSON 載入至頁面,就要透過 {{domxref("XMLHttpRequest")}} API (通常稱為 <strong>XHR</strong>)。此是極好用的 JavaScript 物件,可讓網路請求透過 JavaScript (例如圖片、文字、JSON,甚至 HTML 片段) 來檢索伺幅器的資源,這也代表我們不需載入整個頁面,就能更新小部分的內容。如此可讓網頁反應速度更快;聽起來很棒吧?但可惜本文無法再深入講解更多細節。</p> + +<ol> + <li>一開始,我們先針對要在變數中檢索的 JSON 檔案,將其網址儲存起來。把下列程式碼加到你 JavaScript 程式碼的最下方: + <pre class="brush: js">var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> + </li> + <li>為了建立請求,我們必須透過 <code>new</code> 關鍵字,先從 <code>XMLHttpRequest</code> 建構子建立新的請求物件實例。把下列加到最後一行: + <pre class="brush: js">var request = new XMLHttpRequest();</pre> + </li> + <li>現在用 <code><a href="/en-US/docs/Web/API/XMLHttpRequest/open">open()</a></code> 函式開啟新的請求。加入下列程式碼: + <pre class="brush: js">request.open('GET', requestURL);</pre> + + <p>這樣就顧到至少 2 個參數。當然也有其他參數可選擇。但這個簡易範例只需要 2 個強制參數:</p> + + <ul> + <li>在設立網路請求時,應使用 HTTP 函式。因為這裡只要檢索簡單的資料,所以用 <code><a href="/en-US/docs/Web/HTTP/Methods/GET">GET</a></code> 就可以。</li> + <li>URL 提供請求目的地 — 這也就是我們剛剛儲存的 JSON 檔案網址。</li> + </ul> + </li> + <li>接著加入下面 2 行程式碼。我們為 JSON 設定了 <code><a href="/en-US/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code>,告知伺服器應回傳 JSON 物件,再以 <code><a href="/en-US/docs/Web/API/XMLHttpRequest/send">send()</a></code> 函式傳送請求: + <pre class="brush: js">request.responseType = 'json'; +request.send();</pre> + </li> + <li>最後就是等待由伺服器所回傳的反應,再接著處理。把下列程式碼加入現有程式碼的最下方: + <pre class="brush: js">request.onload = function() { + var superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + </li> +</ol> + +<p>在這裡,我們將所獲得的響應 (可到 <code><a href="/en-US/docs/Web/API/XMLHttpRequest/response">response</a></code> 屬性中找到) 儲存到 <code>superHeroes</code> 變數之中。此變數現在會納入我們的 JSON。接著再把此 JSON 檔案送到 2 個函式呼叫。第一個函式呼叫會將正確資料填入 <<code>header></code>;第二個函式呼叫則會為團隊中的各個英文建立資訊卡,再插入至 <code><section></code> 內。</p> + +<p>當於請求物件上觸發載入事件時,會執行一個事件處理器。我們就將程式碼包裹至此處理器之中 (參閱 <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) — 只要成功回傳響應,就會觸發載入事件。之所以這樣做,是為了確保當我們要以 <code>request.response</code> 進行某件事時,此 <code>request.response</code> 絕對可用。</p> + +<h3 id="產生標頭">產生標頭</h3> + +<p>現在檢索過了 JSON 資料,接著就寫出上面參照過的 2 個函式來利用 JSON 資料吧。首先將下列函式定義加到先前的程式碼中:</p> + +<pre class="brush: js">function populateHeader(jsonObj) { + var myH1 = document.createElement('h1'); + myH1.textContent = jsonObj['squadName']; + header.appendChild(myH1); + + var myPara = document.createElement('p'); + myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed']; + header.appendChild(myPara); +}</pre> + +<p>我們已經將參數命名為 <code>jsonObj</code>,所以在這個函式之內就要用 jsonObj 呼叫此參數。這裡先以 <code><a href="/en-US/docs/Web/API/Document/createElement">createElement()</a></code> 建立 1 組 {{HTMLElement("h1")}} 元素、將其 <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> 指定為 JSON 的 <code>squadName</code> 屬性、透過 <code><a href="/en-US/docs/Web/API/Node/appendChild">appendChild()</a></code> 將之附加到標頭。接著 {{HTMLElement("p")}} 元素依樣畫葫蘆一遍:建立、設定其文字內容、附加到標頭。唯一不同之處,就是將該文字設定為 1 組串接字串 (Concatenated string),其內包含 JSON 的 <code>homeTown</code> 與 <code>formed</code> 屬性。</p> + +<h3 id="建立超級英雄的資訊卡片">建立超級英雄的資訊卡片</h3> + +<p>現在將下列函式加到程式碼底端,用以建立並顯示超級英雄的卡片:</p> + +<pre class="brush: js">function showHeroes(jsonObj) { + var heroes = jsonObj['members']; + + for(i = 0; i < heroes.length; i++) { + var myArticle = document.createElement('article'); + var myH2 = document.createElement('h2'); + var myPara1 = document.createElement('p'); + var myPara2 = document.createElement('p'); + var myPara3 = document.createElement('p'); + var myList = document.createElement('ul'); + + myH2.textContent = heroes[i].name; + myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity; + myPara2.textContent = 'Age: ' + heroes[i].age; + myPara3.textContent = 'Superpowers:'; + + var superPowers = heroes[i].powers; + for(j = 0; j < superPowers.length; j++) { + var listItem = document.createElement('li'); + listItem.textContent = superPowers[j]; + myList.appendChild(listItem); + } + + myArticle.appendChild(myH2); + myArticle.appendChild(myPara1); + myArticle.appendChild(myPara2); + myArticle.appendChild(myPara3); + myArticle.appendChild(myList); + + section.appendChild(myArticle); + } +}</pre> + +<p>我們先把 JSON 的 <code>members</code> 屬性儲存到新的變數中。此陣列所具備的多個物件,均包含了各個超級英雄的資訊。</p> + +<p>接著我們以 <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for 迴圈</a>循環陣列中的各個物件。針對每個物件都會:</p> + +<ol> + <li>建立數個新的元素:1 組 <code><article></code>、1 組 <code><h2>、3 組</code> <code><p>、1 組</code> <code><ul>。</code></li> + <li>讓 <h2> 納入目前超級英雄的 <code>name</code>。</li> + <li>接著 3 個段落分別是英雄的 <code>secretIdentity</code>、<code>age、Superpowers</code>,在列表中帶出相關資訊。</li> + <li>另以新變數 <code>superPowers</code> 儲存 <code>powers</code> 屬性 — 其中包含 1 組陣列以列出目前英雄的超能力。</li> + <li>再用另一個 <code>for</code> 迴圈逐一巡過目前英雄的超能力。針對每一項超能力,我們再建立 1 組 <code><li></code> 元素,把超能力放進該元素之中,再透過 <code>appendChild()</code> 把 <code>listItem</code> 放入 <code><ul></code> 元素之內 (<code>myList</code>)。</li> + <li>最後就是在 <code><article></code> (<code>myArticle</code>) 之內附加 <code><h2>、</code><code><p>、</code><code><ul></code>;再把 <code><article></code> 附加於 <code><section></code> 之內。這附加的順序極為重要,因為這也會是 HTML 中的顯示順序。</li> +</ol> + +<div class="note"> +<p><strong>注意:</strong>如果你無法讓此範例運作,可參閱我們的 <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> 原始碼 (亦可看到<a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">實際執行情況</a>。)</p> +</div> + +<div class="note"> +<p><strong>注意:</strong>如果你無法用我們說過的點記法 (dot-)\括弧記法 (bracket notation) 來存取 JSON,則可用新分頁或自己的文字編輯器開啟 <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> 檔案並參考之。你也可再回去看看 <a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript 物件基礎概念</a> ,再次了解點\括弧記法。</p> +</div> + +<h2 id="物件與文字交互轉換">物件與文字交互轉換</h2> + +<p>上述是存取 JSON 的簡易範例,因為我們設定要回傳響應的 XHR 已經是 JSON 格式。透過:</p> + +<pre class="brush: js">request.responseType = 'json';</pre> + +<p>但有時候沒這麼好運。我們有時會接收到文字字串格式的 JSON 資料,且必須將之轉換為物件。且當我們要以某種訊息傳送 JSON 資料時,也必須將之轉換為字串才能正確運作。還好,這 2 種問題在 Web 開發過程中甚為常見。內建的 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> 物件很早就新增到瀏覽器之中,且包含下列 2 種函式:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code>:接收文字字串形式的 JSON 物件作為參數,並回傳對應的物件。</li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code>:接收 JSON 物件作為參數,並回傳對等的文字字串形式。</li> +</ul> + +<p>你可到 <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> 範例 (參閱<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">原始碼</a>) 中看到第一個函式的運作情形。這其實跟我們先前範例所進行的事情一模一樣,不同之處在於我們設定 XHR 要回傳 JSON 為文字,接著再使用 <code>parse()</code> 轉換為實際的 JSON 物件。關鍵程式碼片段如下:</p> + +<pre class="brush: js">request.open('GET', requestURL); +request.responseType = 'text'; // now we're getting a string! +request.send(); + +request.onload = function() { + var superHeroesText = request.response; // get the string from the response + var superHeroes = JSON.parse(superHeroesText); // convert it to an object + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + +<p>你可能會猜 <code>stringify()</code> 就是反過來運作了吧?可在瀏覽器的 JavaScript 主控台上輸入下列程式碼,看看其運作方式:</p> + +<pre class="brush: js">var myJSON = { "name" : "Chris", "age" : "38" }; +myJSON +var myString = JSON.stringify(myJSON); +myString</pre> + +<p>這樣就建立了 JSON 物件了。接著檢查內容物之後,就可透過 <code>stringify()</code> 將之轉換為字串。將回傳值儲存到新變數之中,再檢查一次即可。</p> + +<h2 id="摘要">摘要</h2> + +<p>我們透過本文簡單介紹了該如何在程式中使用 JSON、該如何建立\剖析 JSON、該如何存取其內的資料。接著就要說明物件導向 JavaScript (OOJS)。</p> + +<h2 id="另可參閱">另可參閱</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON 物件參考頁面</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest 物件參考頁面</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">使用 XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/HTTP/Methods">HTTP 請求函式</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> |