本頁說明如何實作支援圖表工具資料來源通訊協定的服務,使用查詢類別將資料提供給圖表。
目錄
觀眾
本頁資訊主要是協助開發人員自行建立資料來源,而不需要使用圖表工具資料來源。如果您使用該程式庫或其他輔助程式庫,請先閱讀程式庫的說明文件。
本頁內容也可供讀者瞭解,透過何種線路通訊協定在用戶端視覺化和資料來源之間進行通訊。
如果您要建立或使用圖表,則無須閱讀本頁。
為了閱讀這份文件,您應該瞭解基本的 JSON 和 HTTP 要求語法。您也應該從使用者的角度瞭解圖表運作方式。
總覽
您可以實作圖表工具資料來源通訊協定,成為自身圖表或其他圖表的資料來源提供者。圖表工具資料來源會公開名為「資料來源網址」的網址,讓圖表可將 HTTP GET 要求傳送至該網址。做為回應,資料來源會傳回格式正確的資料,以供圖表用於轉譯頁面上的圖形。這個要求回應通訊協定稱為 Google Visualization API 傳輸通訊協定。
資料來源提供的資料可以從檔案或資料庫等各種資源中擷取。唯一的限制是您可以將資料格式設為具有類型資料欄的二維資料表。
做為圖表工具資料來源,您必須以特定格式剖析要求,進而以特定格式傳回回應。大致上有兩種方法:
-
使用下列其中一個輔助程式庫處理要求和回應,並建構要傳回的 DataTable。如果您使用其中一種程式庫,則只需以表格的形式,編寫將資料提供給程式庫所需的程式碼。
- Java 資料來源程式庫:處理要求和回應、根據您提供的資料建立回應資料表,以及實作 Google 圖表工具 SQL 查詢語言。
-
Python 資料來源程式庫:建立回應資料表會產生回應語法。不支援剖析要求或實作 Google 圖表工具 SQL 查詢語言。
或
- 處理要求、建構資料表並傳送回應,以從頭開始寫入自己的資料來源。
運作方式:
- 資料來源會公開一個稱為「資料來源網址」的網址,讓圖表傳送 HTTP GET 要求。
- 用戶端會傳送 HTTP GET 要求,並透過參數描述傳回資料要使用的格式、選填的查詢字串和選用的自訂參數。
- 資料來源接收及剖析要求,如「 要求格式」中所述。
- 資料來源會以要求的格式準備資料,通常為 JSON 資料表。如要瞭解回應格式,請參閱回應格式一節。資料來源可選擇支援 Visualization API 查詢語言,以指定篩選、排序和其他資料操縱。
- 資料來源會建立包含序列化資料和其他回應參數的 HTTP 回應,並如回應格式中所述,將回應傳回用戶端。
注意:本文件中列出的要求和回應 (例如 responseHandler
和「ok」) 的所有參數與字串常數值均小寫,並且會區分大小寫。
基本條件
如要做為圖表工具資料來源,必須符合下列基本條件:
- 這個資料來源應接受 HTTP GET 要求,且應可供用戶端使用。
- 通訊協定可變更並支援版本配置 (目前版本為 0.6),因此資料來源應支援使用舊版和現行版本的要求。新版本發布時,建議您盡早進行支援,以免破壞任何快速升級至最新版本的用戶端。
- 如果要求中傳送了不明屬性,則不失敗。這是因為新版本可能會導入您不知道的新屬性。
- 僅剖析預期屬性。雖然新版本可能會導入新屬性,但請勿盲目接受及使用整個要求字串。為防範惡意攻擊,請謹慎剖析並只使用預期的屬性。
- 如果您不自行編寫用戶端圖表的程式碼,請仔細記錄資料來源要求。包括記錄下列資訊:
- 您接受的任何自訂參數
- 是否可以剖析 Google Visualization API 查詢語言,以及
- 您傳回的資料類型以及資料的結構 (列與欄所代表的內容,以及任何標籤)。
- 對接受不明用戶端要求的網站採取所有標準安全性預防措施。您可以在參數中合理支援 MD5、雜湊和其他安全性機制,藉此驗證要求或協助防範惡意攻擊,並期望用戶端瞭解您的需求並做出回應。不過,如果不是自行編寫圖表程式碼,請務必妥善記錄所有要求。請參閱下方的「安全性考量」一節。
- 所有的要求和回應字串都應採用 UTF-8 編碼。
- 最重要的回應格式為 JSON。請務必先實作 JSON,因為多數圖表都會採用這種格式。請之後再新增其他回應類型。
- 您不一定要支援 Visualization API 查詢語言,但這麼做可以讓資料來源帶給客戶更實用的資訊。
- 您不需要支援任何及所有圖表類型的要求,也可以支援自訂圖表的自訂參數。不過,請以下方所述的標準格式傳回回應。
安全性考量
設計資料來源時,您必須考量資料必須符合的程度。您可以為網站採用多種安全性配置,從簡單的密碼存取到安全的 Cookie 驗證,應有盡有。
隨著圖表出現 XSSI (跨網站指令碼收錄) 攻擊,就很有風險。 使用者可能會前往含有惡意指令碼的網頁,然後開始嘗試透過目前使用者的憑證查詢資料來源網址。如果使用者尚未登出網站,指令碼會以目前的使用者身分進行驗證,並擁有該網站的權限。使用 <script src> 標記,惡意指令碼就能納入資料來源,類似 JSONP。
為了提高安全性,您可以考慮限制要求,這些要求必須來自與資料來源相同的網域。這會大幅限制資料來源的瀏覽權限,但如果您有不應從網域外存取的非常私密資料,則仍建議您考慮這麼做。僅允許來自相同網域要求的資料來源稱為「受限制的資料來源」,而「不受限的資料來源」則不會接受來自任何網域的查詢。以下詳細說明如何導入受限資料來源:
如何確保要求確實來自您的網域,而不是來自外部網域 (或遭到 XSRF 攻擊的網域內的瀏覽器):
- 驗證要求中是否存在「X-DataSource-Auth」標頭。此標頭由 Google Visualization API 定義,您不需要檢查這個標頭的內容,只需驗證標題是否存在。如果您使用的是 Google 圖表工具資料來源程式庫,就可以讓程式庫代為處理。
- 使用 Cookie 驗證來驗證用戶端。目前沒有任何方法能將自訂標頭插入跨網域要求,同時讓驗證 Cookie 保持原樣。
- 將 JavaScript 放在 <script src> 標記時,不太可能執行。方法是在 JSON 回應前面加上 )]},然後加上換行符號。用戶端會從回應中移除前置字串。如果是 XmlHttpRequest,要求源自相同網域時才能使用。
要求格式
用戶端傳送含有數個參數的 HTTP GET 要求,包括自訂元素、選用的查詢字串、簽章和其他元素。您只須負責剖析本節所述的參數,並小心避免處理其他參數,以免遭受惡意攻擊。
請務必備妥選用參數 (標準和自訂) 的預設值,並在網站說明文件中記載所有預設值。
以下提供幾個要求範例 (如需更多要求和回應範例,請參閱本文結尾的「範例」一節):
注意:下列要求字串和「示例」部分中顯示的要求字串必須在傳送前逸出網址。
Basic request, no parameters: http://www.example.com/mydatasource Request with the tqx parameter that contains two properties: http://www.example.com/mydatasource?tqx=reqId:0;sig:4641982796834063168 Request with a query string: http://www.example.com/mydatasource?tq=limit 1
以下是要求字串中的所有標準參數清單。請注意,參數名稱 (例如「version」) 和常數字串值 (例如「ok」、「warning」和「not_modified」) 均區分大小寫。表格也會說明是否需要傳送該參數;如果傳送,則會說明是否需要處理。
參數 | 要求中是否必填? |
資料來源必須處理嗎? |
說明 |
---|---|---|---|
平方 | 否 |
否 |
以 Google Visualization API 查詢語言撰寫的查詢,指定如何篩選、排序或以其他方式操控傳回的資料。字串不需要加上引號。 範例: |
tqx | 否 |
可 |
適用於標準或自訂參數的一組以半形冒號分隔的鍵/值組合。您可以使用分號將組合分開。以下是視覺化通訊協定定義的標準參數清單:
範例: |
TQT | 否 |
否 |
保留:忽略這個參數。用於傳送查詢的方法。 |
回應格式
回應的格式取決於要求的 out
參數,該參數會指定預期的回應類型。請參閱以下各節,瞭解如何回應各個要求類型:
- JSON:傳回包含 JavaScript 物件中資料的 JSON 回應,該物件可直接傳遞至
DataTable
建構函式來填入資料。這是目前最常見的要求類型,最需要妥善實作。 - CSV - 傳回要由瀏覽器處理的固定逗號分隔值清單。
- TSV:傳回要由瀏覽器處理的定位點分隔值清單。
- HTML - 傳回瀏覽器要算繪的 HTML 表格。
您可以使用 Google 視覺化資料來源程式庫 (java) 或視覺化 Python 程式庫產生這些輸出格式。
JSON 回應格式
如果要求包含「X-DataSource-Auth」標頭,則預設回應格式為 JSON,否則為 JSONP。請注意,Google 圖表用戶端實際上支援修改後的 JSON 和 JSONP 版本。如果您使用的是 Java 或 Python 輔助程式,則這些程式庫將顯示您的適當程式碼;如要手動剖析回應,請參閱下方的「JSON 修改」一節。
如果您要強制執行同網域要求,請確認要求中是否存在「X-DataSource-Auth」標頭,並使用授權 Cookie。
這是 Google Visualization API 方法 google.visualization.Query.send()
指定的唯一回應格式。您可以在本頁結尾處查看一些 JSON 要求與回應示例,請見範例。您可以使用 Java 或 Python 輔助程式庫建立這個回應字串。
這個回應格式是 UTF-8 編碼的 JSON 物件 (以大括號 { } 括住的物件,以半形逗號分隔每個屬性),其中包含下表列出的屬性 (資料已指派給 table
屬性)。這個 JSON 物件應包裝在要求的 responseHandler
參數值中。因此,如果要求的 responseHandler
值是「myHandler」,應傳回下列字串 (為求簡潔,只會顯示一個屬性):
"myHandler({status:ok, ...})"
如果要求不包含 responseHandler
值,則預設值為「google.visualization.Query.setResponse」,因此應傳回如下所示的字串 (為求精簡只會顯示一個屬性):
"google.visualization.Query.setResponse({status:ok, ...})"
以下是可用的回應物件成員:
屬性 | 是否必要? |
說明 |
---|---|---|
version | 否 |
一組字串號碼,提供 Google 視覺化電匯通訊協定的版本號碼。如果未指定,用戶端會假設是最新版本。 範例: |
reqId | 是* |
字串號碼,指出此用戶端的要求 ID。如果這個值在要求中,請傳回相同的值。詳情請參閱要求部分中的 reqId 說明。* 如果未在要求中指定此參數,則不需要在回應中設定。 |
status | 可 |
說明這項作業成功或失敗的字串。必須是下列其中一個值,且只能擇一:
範例: |
項警告 | 僅適用於 status=warning |
一或多個物件的陣列,每個物件都說明一個非重大問題。如果為
範例: |
錯誤數 | 如果 status=error ,則為必要欄位 |
一或多個物件的陣列,每個物件都描述錯誤。如果 該陣列具有下列字串成員 (每個成員都只會傳回一個值):
範例:
|
sig | 否 |
資料表物件的雜湊值。適合用於最佳化用戶端與資料來源之間的資料移轉。您可以選擇任何需要的雜湊演算法。 如果您支援這個屬性,應在系統未傳回任何資料時,傳回用戶端傳入的值;如果系統傳回新資料,則應傳回新的雜湊。 範例: |
資料表 | 否 |
JavaScript 常值標記法中的 {cols:[{id:'Col1',label:'',type:'number'}], rows:[{c:[{v:1.0,f:'1'}]}, {c:[{v:2.0,f:'2'}]}, {c:[{v:3.0,f:'3'}]}, {c:[{v:1.0,f:'1'}]} ] }
範例:請參閱下方的範例。 |
Google 的輔助程式庫,以及所有傳送給 Google 的查詢,都會傳回嚴格的 JSON/JSONP。
如果您不是自行剖析傳回的程式碼,就不必擔心。如有需要,您可以使用 JSON.parse() 將 JSON 字串轉換為 JavaScript 物件。雖然 API 處理 JSON 的方式有一項差異,那就是雖然 JSON 不支援 JavaScript 日期值 (例如「new Date(2008,1,28,0,31,26)」)。API 支援以字串形式的有效 JSON 表示法,格式如下:Date(year, month, day[,hour, minute, second[, millisecond]])
表示日期之後的所有項目皆為選用值,而月數則是零。
最佳化 JSON 回應
如果用戶端發出了兩個要求,且要求之間的資料並未變更,則不傳送資料;這樣會浪費頻寬。為了提高要求效率,通訊協定支援在用戶端上快取資料,且如果資料自上次要求後未變更,就會在回應中傳送信號。其計算方式如下:
- 用戶端傳送要求至資料來源。
- 資料來源會產生
DataTable
以及DataTable
物件的雜湊,並在其回應中傳回二者 (雜湊會在tqx.
sig
參數中傳回)。Google Visualization API 用戶端會快取DataTable
和sig
值。 - 用戶端傳送另一個資料要求,包括快取的
tqx.sig
值。 - 資料來源可以透過下列任一方式回應:
- 如果之前要求的資料有所變更,資料來源會傳回新的
DataTable
和新的sig
值雜湊。 - 如果之前要求的資料並未變更,資料來源會傳回
status=error
、reason=not_modified
、sig=old_sig_value
。
- 如果之前要求的資料有所變更,資料來源會傳回新的
- 無論是哪一種情況,代管圖表的網頁都會收到成功回應,並可透過呼叫
QueryResponse.getDataTable()
擷取DataTable
。如果資料相同,則資料就是資料表的快取版本。
請注意,這個方法僅適用於在 Google Visualization API 上建構的圖表所產生的 JSON 要求。
CSV 回應格式
如果要求指定 out:csv
,則回應不會包含中繼資料,而只會以 CSV 格式呈現資料。CSV 資料表通常是以半形逗號分隔的清單,其中每列資料都是以半形逗號分隔的值清單,結尾是 UNIX 換行字元 (\n)。每一欄的儲存格值類型都應相同。第一列是欄標籤,以下是三列 (含三欄) 的資料表範例:
A, B, C 1.0, "yes", true 2.0, "no", false 3.0, "maybe", true
此通訊協定未指定 CSV 格式;資料來源負責定義 CSV 格式。不過,常見格式是一組以半形逗號分隔的值 (沒有空格),並在每一列結尾加上換行符號 (\n)。瀏覽器收到 CSV 字串回覆時,可能會詢問使用者要使用哪個應用程式開啟字串,或直接將其轉譯在畫面上。Java 和 Python 開放原始碼程式庫提供了將 DataTable 轉換為 CSV 字串的方法。
如果要求包含 tqx
參數的 outFileName
成員,請試著在回應標頭中加入指定的檔案名稱。
google.visualization.Query
物件不支援 CSV 回應的要求。如果用戶端想要要求 CSV,您可以在網頁上嵌入視覺化工具列小工具,或使用自訂程式碼建立要求,或者您也可以提供明確設定 tqx
的 out:csv
屬性的連結,如下列要求網址所示:
要求
http://www.example.com/mydatasource?tqx=reqId:1;out:csv
回應
Label 1,Label2\n1,a\n2,b\n3,c\n4,d
TSV 回應格式
如果要求指定 out:tsv-excel
,回應就不會包含中繼資料,而只是以定位點分隔的資料呈現方式,即 utf-16 編碼。如果要求包含 tqx
參數的 outFileName
成員,請試著在回應標頭中加入指定的檔案名稱。
HTML 回應格式
如果要求指定 out:html
,回應應為定義 HTML 表格的 HTML 網頁。這項功能對程式碼偵錯很有幫助,因為瀏覽器可以直接將結果轉譯為可讀取的格式。您無法使用 google.visualization.Query
物件傳送 HTML 回應的查詢。您必須使用自訂程式碼,或在瀏覽器中輸入類似以下網址的網址來查詢 HTML 回應:
要求
http://www.example.com/mydatasource?tqx=reqId:1;out:html
回應
<html><body><table border='1' cellpadding='2' cellspacing='0'><tr style='font-weight: bold; background-color: #aaa;'><td>label 1</td><td>label 2</td></tr><tr bgcolor='#f0f0f0'><td align='right'>1</td><td>a</td></tr><tr bgcolor='#ffffff'><td align='right'>2</td><td>b</td></tr><tr bgcolor='#f0f0f0'><td align='right'>3</td><td>c</td></tr><tr bgcolor='#ffffff'><td align='right'>4</td><td>d</td></tr></table></body></html>
示例
以下是一些要求和回應範例。請注意,要求未經過網址逸出,一般是由瀏覽器或 google.visualization.Query
物件完成。
簡易要求:傳回三欄、四列表格的基本資訊。
Request: http://www.example.com/mydatasource Response google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'ok',sig:'5982206968295329967',table:{cols:[{id:'Col1',label:'',type:'number'},{id:'Col2',label:'',type:'number'},{id:'Col3',label:'',type:'number'}],rows:[{c:[{v:1.0,f:'1'},{v:2.0,f:'2'},{v:3.0,f:'3'}]},{c:[{v:2.0,f:'2'},{v:3.0,f:'3'},{v:4.0,f:'4'}]},{c:[{v:3.0,f:'3'},{v:4.0,f:'4'},{v:5.0,f:'5'}]},{c:[{v:1.0,f:'1'},{v:2.0,f:'2'},{v:3.0,f:'3'}]}]}});
包含回應處理常式的簡易要求:傳回三個資料欄,其中三個資料列資料表含有不同資料類型。
Request: http://www.example.com/mydatasource?tqx=responseHandler:myHandlerFunction Response myHandlerFunction({version:'0.6',reqId:'0',status:'ok',sig:'4641982796834063168',table:{cols:[{id:'A',label:'NEW A',type:'string'},{id:'B',label:'B-label',type:'number'},{id:'C',label:'C-label',type:'datetime'}],rows:[{c:[{v:'a'},{v:1.0,f:'1'},{v:new Date(2008,1,28,0,31,26),f:'2/28/08 12:31 AM'}]},{c:[{v:'b'},{v:2.0,f:'2'},{v:new Date(2008,2,30,0,31,26),f:'3/30/08 12:31 AM'}]},{c:[{v:'c'},{v:3.0,f:'3'},{v:new Date(2008,3,30,0,31,26),f:'4/30/08 12:31 AM'}]}]}});
使用簡易查詢字串的查詢:要求單一資料欄,會傳回包含四個資料列的單一資料欄。
Request: http://www.example.com/mydatasource?tq=select Col1 Response: google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'ok',sig:'6099996038638149313',table:{cols:[{id:'Col1',label:'',type:'number'}],rows:[{c:[{v:1.0,f:'1'}]},{c:[{v:2.0,f:'2'}]},{c:[{v:3.0,f:'3'}]},{c:[{v:1.0,f:'1'}]}]}});
資料未修改錯誤:not_modified
錯誤範例。
Request: http://www.example.com/mydatasource?tqx=reqId:0;sig:4641982796834063168 Response: google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});
資料遭截斷的警告:data_truncated
警告的範例。請注意,這項要求仍會傳回資料。
Request: http://www.example.com/mydatasource?tq=limit 1 Response: google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'warning',warnings:[{reason:'data_truncated',message:'Retrieved data was truncated'}],sig:'1928724788649668508',table:{cols:[{id:'A',label:'NEW A',type:'string'},{id:'B',label:'B-label',type:'number'},{id:'C',label:'C-label',type:'datetime'}],rows:[{c:[{v:'a'},{v:1.0,f:'1'},{v:new Date(2008,1,28,0,31,26),f:'2/28/08 12:31 AM'}]}]}});
存取遭拒錯誤:access_denied
錯誤範例。
Request: http://www.example.com/mydatasource Response: google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'error',errors:[{reason:'access_denied',message:'Access denied',detailed_message:'Access Denied'}]});
查詢字串無效:包含無效查詢字串的要求範例。請注意,詳細訊息是一般訊息,而非實際錯誤訊息。
Request: http://www.example.com/mydatasource?tq=select A Response: google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'error',errors:[{reason:'invalid_query',message:'Invalid query',detailed_message:'Bad query string.'}]});
開發工具
- Java 資料來源程式庫 (來自 Google) - 處理要求和回應、根據您提供的資料建立回應資料表,以及實作 Google 圖表工具 SQL 查詢語言。
- Python 資料來源程式庫 (來自 Google):建立回應資料表,藉此產生回應語法。無法處理剖析要求或實作 Google 圖表工具 SQL 查詢語言。
- MC-Google_Visualization (第三方):這是 PHP 伺服器端程式庫,可以使用 PDO 實作 MySQL、SQLite 和 PostgreSQL 資料庫引擎的圖表工具資料來源。
- bortosky-google-visualization (第三方) - 這個輔助程式庫可為 .NET 使用者建立 Google Visualization API 資料表。
- GV Streamer (第三方):GV Streamer 是伺服器端工具,能將不同來源的資料轉換為 Google 圖表的有效查詢回應。GV Streamer 支援多種語言 (例如 PHP、Java、.NET) 和多種原始資料來源 (例如 MySql)。
- TracGViz (第三方) - TracGViz 是免費的開放原始碼工具,提供元件,讓 Trac 能夠使用圖表小工具,並實作 Trac 管理的資料做為 Google 圖表工具資料來源。
- vis-table (第三方) - 以 PHP 編寫 Google 圖表工具資料來源的程式庫。它分為三個主要部分。資料表實作本身、查詢語言剖析器和格式器。
- 在 Oracle PL/SQL 中的 Google 資料來源實作 (第三方) - 透過 Oracle PL/SQL 套件,可以直接從資料庫將 Oracle 連線至伺服器資料來源。因此,基本上您可以將任何 Oracle 查詢做為 Google 圖表工具資料來源 (套件會傳回內含資料的 JSON 檔案)。它幾乎可以全面支援 Google 查詢語言。