本頁面說明如何實作支援圖表工具資料來源資料來源的服務,並使用查詢類別將資料提供給圖表。
目錄
觀眾
本頁面的主要對像是開發人員,他們若沒有圖表工具資料來源庫,則會自行建立資料來源。如果您使用的是該程式庫或其他輔助程式庫,請先閱讀程式庫的說明文件。
本頁面旨在協助讀者瞭解用於傳輸至用戶端用戶端與資料來源之間的有線通訊協定。
如果您要建立或使用視覺化圖表,則不需要閱讀這個頁面。
如要閱讀這份文件,您應該瞭解基本的 JSON 和 HTTP 要求語法。此外,您也應該瞭解使用者的角度,瞭解圖表的運作方式。
簡介
您可以實作圖表工具資料來源來源通訊協定,藉此成為您自己或其他圖表的資料來源提供者。圖表工具資料來源會顯示一個網址,稱為資料來源網址,圖表可將此網址傳送至 HTTP GET 要求。做為回應,資料來源會傳回格式正確的資料,以圖表呈現頁面上的圖形。這個要求回應通訊協定又稱為 Google 視覺化 API 傳輸通訊協定。
資料來源提供的資料可以從各種資源 (例如檔案或資料庫) 中擷取。唯一的限制是,您可以將資料格式化為具有指定資料欄的二維表格。
作為圖表工具資料來源,您必須剖析特定格式的要求,並以特定格式傳回回應。您可以選擇以下其中一種方法:
-
使用下列其中一個輔助程式庫來處理要求和回應,並建構要傳回的 DataTable。如果您使用其中一種程式庫,您只需要撰寫程式碼,即可將資料以表格的形式提供給資料庫。
- Java 資料來源程式庫 - 處理要求和回應、使用您提供的資料建立回應資料表,並實作 Google Chart Tools SQL 查詢語言。
- Python 資料來源程式庫 - 建立回應資料表會產生回應語法。無法處理剖析要求或實作 Google 圖表工具 SQL 查詢語言。
或者
- 透過處理要求、建構 DataTable 以及傳送回應,從頭開始撰寫自己的資料來源。
運作方式:
- 資料來源會顯示一個網址,稱為資料來源網址,圖表會透過該網址傳送 HTTP GET 要求。
- 用戶端發出 HTTP GET 要求,並透過參數說明傳回的資料使用何種格式、選用查詢字串,以及選用的自訂參數。
- 資料來源按照要求格式所述方式接收及剖析要求。
- 資料來源按照要求的格式準備資料,通常是 JSON 資料表。回應格式則在回應格式一節中說明。資料來源可視需要支援視覺化 API 查詢語言,該篩選器可指定篩選、排序和其他資料操控方式。
- 資料來源會建立 HTTP 回應,其中包含序列化資料和其他回應參數,並依照回應格式所述傳回該用戶端。
注意:本文件中列出的要求和回應 (例如 responseHandler
和「ok」) 的所有參數和字串常數值皆為小寫,且區分大小寫。
基本條件
以下是使用圖表工具資料來源的最低需求:
- 資料來源應接受 HTTP GET 要求,且應提供給您的用戶端。
- 通訊協定可變更並支援版本配置 (目前版本為 0.6),因此您的資料來源應支援使用先前版本和目前版本的要求。建議您在推出後盡快支援新版本,以免任何用戶端升級至最新版本。
- 如果要求傳送不明屬性,請勿執行此動作。這是因為新版本可能會導入您沒有註意到的新屬性。
- 僅以您預期為基準來銷售。雖然新版本可能會引入新屬性,但請勿盲目接受並使用整個要求字串。為避免您受到惡意攻擊,請務必謹慎使用並僅使用您預期的屬性。
- 如果您沒有自行編寫用戶端圖表,請妥善記錄資料來源需求。包括記錄下列資訊:
- 您接受的任何自訂參數
- 您是否能剖析 Google 視覺化 API 查詢的語言,以及
- 您傳回的資料類型,以及資料的結構 (列和欄的意義以及任何標籤)。
- 針對接受未知用戶端要求的網站採取所有標準安全性預防措施。您可以合理支援參數中的 MD5、雜湊和其他安全機制,以便驗證要求或協助防範惡意攻擊,並期望用戶端瞭解需求並回應這些要求。不過,如果您並未自行編寫圖表,請務必妥善記錄所有規定。請參閱下方的安全性考量。
- 所有要求和回應字串都必須以 UTF-8 編碼。
- 最重要的回應格式是 JSON。請務必先實作 JSON,因為這是大部分圖表使用的格式。在此之後,請新增其他回應類型。
- 您「不必」支援視覺化 API 查詢語言,但可以讓資料來源更實用。
- 您不需要支援任何和所有圖表類型的要求,而且可以支援自訂圖表的自訂參數。不過,您應該依照下列標準格式傳回回應。
安全性考量
設計資料來源時,您需要考量資料的安全程度。網站有多種安全性機制,從簡單的密碼存取,到安全 Cookie 驗證,您都能使用。
XSSI (涵蓋跨網站指令碼攻擊) 攻擊可能會帶來圖表風險。 使用者可能會前往含有惡意指令碼的網頁,接著使用目前使用者的憑證,開始嘗試查詢資料來源網址。如果使用者未登出某個網站,指令碼便會驗證為目前的使用者,並擁有該網站的權限。如果使用 <script src> 標記,惡意指令碼就能加入資料來源,與 JSONP 類似。
為了提升安全性,您可以考慮限制來自相同資料來源網域的要求。這樣做會大幅限制資料來源的瀏覽權限,但如果您的機密資料不應透過網域外存取,請考慮使用。只允許來自相同網域的要求,屬於受限資料來源,而「未限制的資料來源」則可接受來自任何網域的查詢。以下將詳細說明如何實作受限的資料來源:
如何確保要求確實來自您的網域,而非來自外部網域 (或屬於 XSRF 攻擊下的網域):
- 驗證要求中是否有「X-DataSource-Auth」標頭。 這個標題是由 Google 視覺化 API 定義;您不需要檢查這個標頭的內容,只要驗證標頭即可。如果您使用的是 Google 圖表工具資料來源資料庫,則可讓程式庫為您處理這個問題。
- 使用 Cookie 驗證來驗證用戶端。目前沒有已知方法可在跨網域要求中插入自訂標頭,同時保留驗證 Cookie。
- 加入 <script src> 標記時,讓 JavaScript 不太可能執行。方法是在 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
以下是要求字串中所有標準參數的清單。請注意,參數名稱 (例如「版本」) 和常數字串值 (例如「ok」、「warning」與「not_modified」) 均區分大小寫。下表也會說明是否需要傳送參數,以及是否需要傳送參數。
參數 | 在「要求」中為必填? |
必須處理資料來源? |
說明 |
---|---|---|---|
平方 | 否 |
否 |
以 Google 視覺化 API 查詢語言編寫的查詢,可指定如何篩選、排序或操控傳回的資料。字串不需要加上引號。 範例: |
tqx | 否 |
可 |
一組用於冒號或自訂參數的冒號分隔鍵/值組合。並使用半形分號分隔。以下是視覺化通訊協定定義的標準參數清單:
範例: |
tqrt | 否 |
否 |
已保留:忽略這個參數。用來傳送查詢的方法。 |
回應格式
回應的格式取決於要求的 out
參數,該參數會指定預期的回應類型。請參閱下列各節,瞭解如何回應各種要求類型:
- JSON - 傳回 JSON 回應,其中包含 JavaScript 物件中的資料,可直接傳遞至
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 視覺化 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 視覺化傳輸通訊協定通訊協定版本號碼。如未指定,則用戶端會更新至最新版本。 範例: |
要求 | 是* |
字串,表示這個用戶端此要求的 ID。如果要求中包含,則傳回相同的值。詳情請參閱要求部分中的 reqId 說明。* 如果要求中未指定此參數,您就不需要在回應中設定此參數。 |
狀態 | 可 |
用來表示作業成功或失敗的字串。必須是下列其中一個值:
範例: |
項警告 | 僅適用於 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 視覺化 API 用戶端會快取DataTable
和sig
的值。 - 用戶端會傳送另一個資料要求,包括快取的
tqx.sig
值。 - 資料來源可透過下列其中一種方式回應:
- 如果資料已從先前的要求中改變,資料來源會傳回新的
DataTable
和新的sig
值雜湊值。 - 如果資料與先前的要求不同,資料來源就會傳回
status=error
、reason=not_modified
、sig=old_sig_value
。
- 如果資料已從先前的要求中改變,資料來源會傳回新的
- 無論是哪一種情況,代管圖表的網頁都會成功回應,並可透過呼叫
QueryResponse.getDataTable()
來擷取DataTable
。如果資料相同,則這只是資料表的快取版本。
請注意,這項功能僅適用於透過 Google 視覺化 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 Chart Tools SQL 查詢語言。
- Python 資料來源資料庫 (來自 Google) - 建立回應資料表會產生回應語法。無法處理剖析要求或實作 Google 圖表工具 SQL 查詢語言。
- MC-Google_Visualization (第三方):這是一項 PHP 伺服器端程式庫,可供您使用 PDO 實作 MySQL、SQLite 和 PostgreSQL 資料庫引擎的圖表工具資料來源。
- bortosky-google-visualization (第三方):這是專為 .NET 使用者建立 Google 視覺化 API 資料表的輔助程式庫。
- GV Streamer (第三方):GV Streamer 是一項伺服器端工具,可將不同來源的資料轉換為 Google 圖表的有效查詢回應。GV Streamer 支援多種語言 (例如 PHP、Java、.NET) 與數個原始資料來源 (例如 MySql)。
- TracGViz (第三方) - TracGViz 是一款免費的開放原始碼工具,提供設定元件,讓 Trac 能使用圖表小工具,並實作 Trac 管理的資料做為 Google 圖表工具的資料來源來源。
- vis-table (第三方):在 PHP 中實作 Google Chart Tools 資料來源的程式庫。主要分為三個部分。資料表的實作本身、查詢語言剖析器和格式轉換程式。
- Oracle PL/SQL 中的 Google 資料來源實作 (第三方) - 一種 Oracle PL/SQL 套件,可讓 Oracle 直接從資料庫建立資料來源。基本上,您可以使用任何 Oracle 查詢做為 Google Chart Tools 資料來源 (套件將傳回含有資料的 JSON 檔案)。Google Cloud 語言幾乎可以支援 Google Query Language。