リモート コンテンツの処理

このドキュメントでは、リモート テキスト (通常は HTML)、XML、JSON、RSS/Atom フィードのデータをフェッチして処理する方法について説明します。

目次

  1. はじめに
  2. さまざまなコンテンツ タイプの処理
    1. テキストの処理
    2. XML の処理
    3. フィードの処理
    4. JSON の処理
  3. 認可タイプの設定
  4. メソッド
    1. GET
    2. POST
  5. キャッシュの更新

概要

ガジェットの魅力的な機能として、新たな方法で複数のソースからの情報を統合できる機能や、既存の情報とのやり取りに別の方法を提供できる機能があります。Gadgets API を使用すると、他のウェブ サーバーやウェブページからリモート コンテンツをフェッチし、処理できます。

Gadgets API では、リモート ウェブ コンテンツの取得と処理のために、makeRequest(url, callback, opt_params) 関数を提供しています。この関数には、次の引数を指定します

  • String url - コンテンツがある URL です。
  • Function callback - URL からデータをフェッチした後、そのデータを使用して呼び出す関数です。
  • Map.<gadgets.io.RequestParameters, Object> opt_params - リクエストに渡す追加パラメータです。

opt_params 引数には、以下を指定できます。

  • リクエストのコンテンツ タイプ (TEXTXMLFEEDJSON)
  • リクエストのメソッド タイプ (POST または GET)
  • リクエストに含めるヘッダー
  • 認可タイプ (NONESIGNEDOAUTH )

注:makeRequest()type="url" のガジェットで使用することはできません。

フェッチするデータの種類によらず、makeRequest() への呼び出しには次の共通の特徴があります。

  • 最初のパラメータは URL で、リモート コンテンツのフェッチに使用されます。
  • 2 番目のパラメータは、コールバック関数で、返されたデータの処理のために使用されます。
  • 呼び出しは非同期なので、コールバック関数内ですべての処理を始める必要があります。コールバックとは、別の関数にパラメータとして (関数参照の形式で) 渡される関数のことです。コールバックは、実行中のフレームワークでサードパーティのデベロッパーが何らかの処理をするための「フック」となります。
  • 呼び出しはすぐに戻るので、戻り値はなく、応答が返るたびに、関連付けられたコールバック関数が呼び出されます。

たとえば次のコード スニペットでは、リモート コンテンツをテキストとしてフェッチしています。このコードは、google.com ウェブページの HTML テキストをフェッチし、最初の 400 文字を表示します。

function getHtml() {    
  var params = {};  
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;  
  var url = "http://www.google.com";  
  gadgets.io.makeRequest(url, response, params);
};
function response(obj) {  
  //obj.text contains the text of the page that was requested  
  var str = obj.text;
  var html =  str.substr(0,400);  
  document.getElementById('content_div').innerHTML = html;
};
gadgets.util.registerOnLoadHandler(getHtml);

この例では、makeRequest() の機能の背後にある基本的な考え方を示しています。

  1. makeRequest() が呼び出されると、Gadgets API は、関数に渡された URL (この例では URL は http://www.google.com) に非同期の HTTP GET リクエストを行います。
  2. makeRequest()フェッチが終了するとすぐに戻り、その後でコールバック関数を呼び出します (この例では response() が呼ばれます)。そのため従属コードはすべて、コールバック関数内またはコールバック関数から呼び出される関数内に含める必要があります。
  3. makeRequest()次の構造を持つ JavaScript オブジェクトを返します。
{
  data : <parsed data, if applicable>,
  errors : <any errors that occurred>,
  text : <raw text of the response>  
}  

このオブジェクトは、コールバック関数に指定される唯一の引数です。コールバック関数では、返されたこのデータに対して何らかの処理をします。典型的な処理では、データの一部を抽出し、HTML マークアップと組み合わせ、その結果の HTML をガジェットに表示します。

さまざまなコンテンツ タイプの処理

デフォルトでは、リモート ウェブサイトのコンテンツはテキストとして返されます。opt_params フィールドを使用すると、返されるコンテンツのタイプを次のいずれかのコンテンツ タイプに設定できます。

  • TEXT -- gadgets.io.ContentType.TEXT
  • DOM -- gadgets.io.ContentType.DOM
  • FEED -- gadgets.io.ContentType.FEED
  • JSON -- gadgets.io.ContentType.JSON

テキストの処理

次の例では、CSV (カンマ区切り) ファイルからデータをフェッチし、それを使って個人の連絡先のリストに入力します。ここでは、オプションのパラメータにフェッチするコンテンツのコンテンツ タイプを設定する方法を示しています。response(obj) コールバック関数では、obj.text を使用してテキスト値を obj から抽出しています。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch Text Example"/>
  <Content type="html">
  <![CDATA[
  <div id="content_div"></div>
  <script type="text/javascript">

  // This example fetches data from a CSV file containing contact information. In the CSV file, 
  // each record consists of a name, email address, and phone number.
  function getContacts() {
    var params = {};  
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;  
    var url = "http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/Contacts.csv";
    gadgets.io.makeRequest(url, response, params);
  };
  // Callback function to process the response
  function response(obj) {               
    var responseText = obj.text;  
    // Set CSS for div.
    var html = "<div style='padding: 5px;background-color: #FFFFBF;font-family:Arial, Helvetica;" 
    + "text-align:left;font-size:90%'>"; 

    // Use the split function to extract substrings separated by comma 
    // delimiters.
    var contacts = responseText.split(",");
    // Process array of extracted substrings.
    for (var i = 0; i < contacts.length ; i++) {
      // Append substrings to html.
      html += contacts[i]; 
      html += " ";

      // Each record consists of 3 components: name, email, and
      // phone number. The gadget displays each record on a single
      // line:
      //
      // Mickey Mouse mickey@disneyland.com 1-800-MYMOUSE
      //
      // Therefore, insert a line break after each (name,email,phone)
      // triplet (i.e., whenever (i+1) is a multiple of 3).
      if((i+1)%3 ==0) { 
        html += "<br>";
      }
    }
    html += "</div>";
    // Output html in div.
    document.getElementById('content_div').innerHTML = html;
  }
  gadgets.util.registerOnLoadHandler(getContacts);

 </script>
  ]]>
  </Content>
</Module>

XML の処理

Document Object Model (DOM) は、HTML と XML ドキュメントを操作するための API です。makeRequest() を使用すると、XML ドキュメントを DOM オブジェクトとして取得できます。取得したオブジェクトは、標準の DOM JavaScript 関数を使用して処理できます。典型的な処理としては、XML ファイルから必要なデータを抽出し、HTML や CSS のマークアップと組み合わせ、その結果の HTML をガジェットに表示します。

DOM を使用すると、ウェブ コンテンツはノードのツリーとして解析されます。例として次の HTML のスニペットがあります。

<a href="http://www.google.com/">Google's <b>fast</b> home page.</a>

このスニペットでは、このセクションで説明するノードの主なタイプを示しています。

  • 要素ノード。このスニペットの要素ノードは、ab です。要素ノードは、ドキュメントの構造を定義する構成要素です。
  • テキスト ノード。このスニペットのテキスト ノードは、Google’sfasthome page です。テキスト ノードは常に要素ノードの中に含まれています。テキスト ノードは、そのノードを含んでいる要素ノードの子ノードです。
  • 属性ノード。このスニペットの属性ノードは、href="http://www.google.com" 1 つです。属性ノードは、そのノードを含んでいる要素ノードの追加情報を示します。ただし属性ノードは、そのノードを含んでいる要素の子ノードとは見なされません。これは、属性ノードの処理に影響します。このトピックに関して詳しくは、さまざまなノード タイプの処理をご覧ください。

この HTML スニペットの DOM 構造は次のようになります。

DOM ツリー

DOM オブジェクト内のデータにアクセスするには、DOM 関数を使用してノードの親子関係を移動することで、「ツリーをたどって」、アクセスが必要なデータに到達します。

次の XML ファイルには、朝食の一連の項目のデータが含まれています。最上位の親ノードは menu で、その下に複数の food 子ノードがあります。menuノードには、属性ノードtitle="Breakfast Menu" も含まれています。各 food ノードには、namepricedescriptioncalories の子ノードがあります。

namepricecalories の各ノードには、それぞれの「テキスト」の子ノードがあります。各 description ノードには CDATA 子ノードが含まれています。CDATA は、特殊なノード タイプです。CDATA セクションは、通常はマークアップとして認識される文字 (山かっこなど) を含むテキストをまとめてエスケープするために使用されます。CDATA セクションで認識される唯一の区切り文字は、CDATA セクションの最後にある「]]>」文字列です。

<?xml version="1.0" encoding="UTF-8" ?>
<menu title="Breakfast Menu">
  <food>
     <name>Early Bird Breakfast</name> 
     <price>$3.95</price> 
     <description><![CDATA[<div style="color:purple; padding-left:25px;">Two eggs any style with your choice of bacon 
or sausage, toast or English muffin.</div>]]></description> 
     <calories>450</calories> 
  </food>

  <food>
     <name>Chocolate Chip Belgian Waffles</name> 
     <price>$7.95</price> 
     <description><![CDATA[<div style="color:purple; padding-left:25px;">Chocolate chip Belgian waffles covered with 
chocolate syrup and whipped cream.</div>]]></description> 
     <calories>900</calories> 
 </food>

     …
</menu>

次のサンプル ガジェットでは、この XML ファイルをデータ ソースとして使用します。このガジェットでは、朝食のメニューが表示され、ユーザーはカロリーの上限を設定できます。指定した上限を超えるカロリーは、赤い字で表示されます。ユーザーは、朝食の各項目の説明を表示するかどうかを選択することもできます。

次のコードでは、さまざまなタイプのノードからデータを抽出するために DOM ツリーをたどる方法と、そのデータを HTML や CSS のマークアップと組み合わせて、朝食メニューのガジェットに表示する方法の例を示します。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch XML" scrolling="true"/>
  <UserPref 
    name="mycalories" 
    display_name="Calorie limit" 
    default_value="800"/>
  <UserPref 
    name="mychoice" 
    display_name="Show Descriptions" 
    datatype="bool" 
    default_value="false"/>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript">
      // get prefs
      var prefs = new gadgets.Prefs();
      // Calorie limit set by user
      var calorieLimit = prefs.getString("mycalories");
      // Indicates whether to show descriptions in the breakfast menu    
      var description = prefs.getBool("mychoice");

      function makeDOMRequest() {    
        var params = {};  
        params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;  
        var url = "http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/breakfast-data.xml";  
        gadgets.io.makeRequest(url, response, params);
      };
      function response(obj) { 
        // Start building HTML string that will be displayed in <div>.           
        // Set the style for the <div>.        
        var html = "<div style='padding: 5px;background-color: #ccf;font-family:Arial, Helvetica;" 
          + "text-align:left;font-size:90%'>";   
        // Set style for title.
        html +="<div style='text-align:center; font-size: 120%; color: yellow; " 
          + "font-weight: 700;'>"; 
        // obj.data contains a Document DOM element corresponding to the
        // page that was requested
        var domdata = obj.data;

        // Display menu title. Use getElementsByTagName() to retrieve the <menu> element.
        // Since there is only one menu element in the file,
        // you can get to it by accessing the item at index "0". 
        // You can then use getAttribute to get the text associated with the
        // menu "title" attribute.
        var title = domdata.getElementsByTagName("menu").item(0).getAttribute("title");

        // Alternatively, you could retrieve the title by getting the menu element node
        // and calling the "attributes" function on it. This returns an array
        // of the element node's attributes. In this case, there is only one
        // attribute (title), so you could display the value for the attribute at
        // index 0. For example:
        // 
        // var title = domdata.getElementsByTagName("menu").item(0).attributes.item(0).nodeValue; 

        html += title + "</div><br>"; 
        // Get a list of the <food> element nodes in the file
        var itemList = domdata.getElementsByTagName("food");
 
        // Loop through all <food> nodes
        for (var i = 0; i < itemList.length ; i++) { 
        // For each <food> node, get child nodes.
        var nodeList = itemList.item(i).childNodes;

        // Loop through child nodes. Extract data from the text nodes that are
        // the children of the associated name, price, and calories element nodes.
        for (var j = 0; j < nodeList.length ; j++) {
          var node = nodeList.item(j);
          if (node.nodeName == "name") 
          {
            var name = node.firstChild.nodeValue;
          }
          if (node.nodeName == "price") 
          {
            var price = node.firstChild.nodeValue;
          }
          if (node.nodeName == "calories") 
          {
            var calories = node.firstChild.nodeValue; 
          }
          // If the user chose to display descriptions and
          // the child node is "#cdata-section", grab the 
          // contents of the description CDATA for display.
          if (node.nodeName == "description" && description==true)
          {
            if (node.firstChild.nodeName == "#cdata-section") 
              var data = node.firstChild.nodeValue;
          }
        } 
        // Append extracted data to the HTML string.
        html += "<i><b>";
        html += name;
        html += "</b></i><br>";
        html += "&emsp;"; 
        html += price;
        html += " - ";
        // If "calories" is greater than the user-specified calorie limit,
        // display it in red.
        if(calories > calorieLimit) {
          html += "<font color=#ff0000>";
          html += calories + " calories";
          html += " </font>"; 
        }
        else
          html += calories + " calories";
        html += "<br>";
        // If user has chosen to display descriptions
        if (description==true) 
        {
          html += "<i>" + data + "</i><br>";
        } 
      } 
      // Close up div
      html += "</div>";
      document.getElementById('content_div').innerHTML = html;
    };
    gadgets.util.registerOnLoadHandler(makeDOMRequest);
    </script>
  ]]>
  </Content>
</Module>

このサンプル コードでは、DOM データのやり取りに使用する次の 4 つの主要な関数を使用しています。

  • getElementsByTagName(tagname) -- DOM ドキュメントについて、tagname と一致する名前の要素ノードを配列にして返します。ワイルドカード文字 (*) を使用すると、ファイル内のすべての要素ノードを取得できます。たとえば <t code="<span class="style3">" id="135"/>response.getElementsByTagName("*")response.getElementsByTagName("*")と指定します。
  • getElementById(id) -- DOM ドキュメントについて、id で指定されたノードを 1 つ取得します。
  • getAttribute(attrib) -- 要素ノードの属性 attrib を返します。例を次に示します。response.getElementsByTagName("menu").item(0).getAttribute("title")
  • attributes -- 要素ノードについて、そのノードの属性を配列にして返します。

上記の例では、DOM ツリーをたどるさまざまな関数のほんの一部のみを示しています。通常使用する関数は他に、lastChildnextSiblingpreviousSiblingparentNode などがあります。

さまざまなノード タイプの処理

DOM を効率よく処理するには、さまざまなノードのタイプの微妙な違いを認識することが重要な場合があります。

ノード タイプ 説明 戻り値 注意
element ドキュメントの構成要素。<p><b><calories> など。 nodeName: 山かっこで囲まれたテキスト。たとえば <menu>nodeName は、menu です。

nodeType: 1

nodeValue : null
要素ノードの nodeValuenull です。要素ノードに関連付けられたテキスト ノードや属性ノードの値を取得するには、それらのノードにアクセスする必要があります。たとえばテキスト ノードは element.firstChild.nodeValue と指定し、属性は element.getAttribute(attrib) と指定します。
text テキスト。テキスト ノードは、常に要素ノードの中に含まれています。要素ノードの子ノードです。 nodeName: #text

nodeType: 3

nodeValue: ノードに含まれているテキストです。
ブラウザによっては、ドキュメント内のすべての空白をテキスト ノードとするので、DOM オブジェクトに「空」のテキスト ノードが含まれる場合があります。そのために、ツリーをたどる際に予期しない結果が発生することがあります。解決策としては、改行文字しか含まないテキスト ノードをただ除外するか、処理を強化することが考えられます。このトピックに関して詳しくは、Whitespace in the DOM をご覧ください。
attribute キーと値のペアで、要素ノードに関する追加情報を指定します (例 title="my document")。属性ノードは、要素ノードに含まれますが、要素ノードの子ノードではありません。 nodeName: 属性のペアの左側の値です。属性が title="my document" の場合、nodeNametitle です。

nodeType: 2

nodeValue: 属性ペアの右側の値です (この例では ”my document”)。
属性は、要素ノードに含まれているノードですが、要素ノードの子ノードではありません。属性は Node インターフェースから継承されますが、DOM ではそれを DOM ツリーの一部とは見なしません。そのため、属性ノードにノード関数の多く (nodeNamenodeValuenodeType など) を使用できますが、DOM ツリーをたどる関数を使用して属性ノードにアクセスすることはできません。属性にアクセスするには、関数 attributesgetAttribute(attrib) を使用します。
CDATA コンテンツを解析しないで、そのままにしておくセクションです。CDATA セクションは、通常はマークアップとして認識される文字を含むテキストをまとめてエスケープするために使用されます。CDATA セクションで認識される唯一の区切り文字は、CDATA セクションの最後にある「]]>」文字列です。 nodeName: #cdata-section

nodeType: 4

nodeValue: CDATA 区切り文字で囲まれたテキストとマークアップです。

CDATA セクション内のテキストには、独自のマークアップが含まれています。これは、ガジェットの中に組み込む際に影響を与える可能性があります。
その他のリソース

フィードの処理

コンテンツ ディレクトリの [フィードやガジェットを追加] に URL を入力すると、自分の iGoogle ページにフィードを追加できます。これは、Gadgets API の組み込みのフィード サポートを使用して、フィード用のガジェットを作成して、iGoogle に追加しています。この機能は簡単に利用できますが、コンテンツや表示をカスタマイズすることはできません。また、他のコンテナで使用することもできません。

さらに高度なフィード処理を行う場合は、makeRequest() メソッドを使って FEED コンテンツ タイプを指定できます。フィード リクエストは、ATOM/RSS XML フィードを解析し、JSON エンコードされたオブジェクトとしてレスポンスを返そうとします。

FEED コンテンツ タイプでは、次のパラメータを指定できます。

パラメータ データ型 説明
gadgets.io.RequestParameters.NUM_ENTRIES Number、オプション フィードから取得するフェード エントリの数です。1~100 の値を指定できます。デフォルトは 3 です。
gadgets.io.RequestParameters.GET_SUMMARIES Boolean、オプション フィード内の各エントリのサマリーをフル テキストで取得するかどうか。デフォルトは false です。true に設定する必要があるのは、データを使用する場合のみです。サマリーをフル テキストで受け取ると容量が膨大になる場合があるため、サマリーを不必要に転送しないでください。

JSON フィード オブジェクト内のフィールドは次のとおりです。

フィールド 説明
ErrorMsg 定義されている場合は、発生したすべてのエラーが記述されます。
URL RSS/Atom フィードの URL です。
Title フィードのタイトルです。
Description フィードの簡単な説明です。
Link 通常は、フィードのホームページの URL が指定されます。
Author フィードの作成者です。
Entry フィード エントリの配列です。次のフィールドはエントリ内でネストされます。
  • Title. このフィード エントリのタイトルです。
  • Link. このフィード エントリの URL です。
  • Summary. このフィード エントリのコンテンツまたはサマリーです。
  • Date. このエントリのタイムスタンプです。1970 年 1 月 1 日からの経過秒で表されます。正確な日時で JavaScript Date オブジェクトを初期化するために必要なミリ秒に変換するには、1,000 を掛けます。詳しくは、以下のガジェット コード例をご覧ください。

たとえば次の RSS フィードを考えます。

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<rss version="2.0">
<channel>
<title>Code Examples for makeRequest()</title>
<link>http://code.google.com/apis/gadgets/docs/remote-content.html</link>
<description>This feed lists code examples for the gadgets.* makeRequest() function.</description>
<language>en</language>
<item>
<title>Fetch Text Example</title>
<link>http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-csv.xml</link>
<description>This example illustrates how to use makeRequest() with text content.</description>
<author>Google</author>
<pubDate>Sat, 09 Aug 2008 11:46:09 UT</pubDate> </item>
<item>
<title>Fetch XML Example</title>
<link>http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-XML.xml</link>
<description>This section describes how to use makeRequest() with XML content.</description>
<author>Google</author>
<pubDate>Sat, 09 Aug 2008 11:46:09 UT</pubDate>
</item>
<item>
<title>Feed Fetch Example</title>
<link>http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/feed-fetch.xml</link>
<description>This example illustrates how to use makeRequest() with Feed content.</description>
<author>Google</author>
<pubDate>Sat, 09 Aug 2008 10:33:09 UT</pubDate>
</item>
<item>
<title>Fetch JSON Example</title>
<link>http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-json.xml</link>
<description>This example illustrates how to use makeRequest() with JSON content.</description>
<author>Google</author>
<pubDate>Sat, 09 Aug 2008 03:55:28 UT</pubDate> </item>
</channel>
</rss>

FEED コンテンツ タイプを使って上記のフィードをフェッチする場合、戻り値は JSON 文字列として次のようにエンコードされます。

{"Entry":
  [
    {
      "Link":"http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-csv.xml",
      "Date":1218282369000,
      "Title":"Fetch Text Example",
      "Summary":"This example illustrates how to use makeRequest() with text content."
    },
    {
      "Link":"http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-XML.xml",
      "Date":1218282369000,
      "Title":"Fetch XML Example",
      "Summary":"This section describes how to use makeRequest() with XML content."
    },
    {
      "Link":"http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/feed-fetch.xml",
      "Date":1218277989000,
      "Title":"Feed Fetch Example",
      "Summary":"This example illustrates how to use makeRequest() with Feed content."
    },
    {
      "Link":"http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/fetch-json.xml",
      "Date":1218254128000,
      "Title":"Fetch JSON Example",
      "Summary":"This example illustrates how to use makeRequest() with JSON content."
    }
  ],
  "Description":"This feed lists code examples for the gadgets.* makeRequest() function.",
  "Link":"http://code.google.com/apis/gadgets/docs/remote-content.html",
  "Author":"Google",
  "URL":"http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/sample-gadgets-feed.xml",
  "Title":"Code Examples for makeRequest()"
}
    

次の例では、makeRequest() を使用してフィードをフェッチし、そのデータの一部をガジェットに表示する方法を示します。ガジェットを示します。そのガジェットは、ガジェット デベロッパー フォーラムからのエントリを含むフィードをフェッチします。ユーザーは次の指定ができます。

  • 表示するエントリの数
  • 各エントリの日付をガジェットが表示する必要があるかどうか
  • 各エントリのサマリーをガジェットが表示する必要があるかどうか

この例のコードは次のとおりです。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch Feed Example" 
    title_url="http://groups.google.com/group/Google-Gadgets-API" 
    scrolling="true">
  </ModulePrefs>
  <UserPref name="show_date" display_name="Show Dates?" datatype="bool" default_value="false"/>
  <UserPref name="num_entries" display_name="Number of Entries:" default_value="5"/>
  <UserPref name="show_summ" display_name="Show Summaries?" datatype="bool" default_value="false"/>
  <Content type="html">
  <![CDATA[
  <style> #content_div { font-size: 80%;  margin: 5px; background-color: #FFFFBF;} </style>
  <div id="content_div"></div>
  <script type="text/javascript">

  // Get userprefs
  var prefs = new gadgets.Prefs();
  var showdate = prefs.getBool("show_date");
  var entries = prefs.getInt("num_entries");
  var summaries = prefs.getBool("show_summ");

  function getFeed() {  
    var params = {};  
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;  
    params[gadgets.io.RequestParameters.NUM_ENTRIES] = new Number(entries);  
    params[gadgets.io.RequestParameters.GET_SUMMARIES] = summaries; 
    var url = "http://groups.google.com/group/Google-Gadgets-API/feed/rss_v2_0_msgs.xml";  
    gadgets.io.makeRequest(url, response, params);
  };

  function response(obj) { 
    // obj.data contains the feed data
    var feed = obj.data;
    var html = "";

    // Display the feed title and description
    html += "<div><b>" + feed.Title + "</b></div>";
    html += "<div>" + feed.Description + "</div><br>";
      
    // Access the data for a given entry
    if (feed.Entry) {
      for (var i = 0; i < feed.Entry.length; i++) {
        html += "<div>"
          + "<a target='_blank' href='" + feed.Entry[i].Link + "'>"
          + feed.Entry[i].Title
          + "</a> ";
        if (showdate==true)
        { 
          // The feed entry Date field contains the timestamp in seconds
          // since Jan. 1, 1970. To convert it to the milliseconds needed
          // to initialize the JavaScript Date object with the correct date, 
          // multiply by 1000.
          var milliseconds = (feed.Entry[i].Date) * 1000; 
          var date = new Date(milliseconds); 
          html += date.toLocaleDateString();
          html += " ";
          html += date.toLocaleTimeString(); 
        }
        if (summaries==true) { 
          html += "<br><i>" + feed.Entry[i].Summary + "</i>";
        }
        html += "</div>";
      }
    }        
    document.getElementById('content_div').innerHTML = html;
  };
  gadgets.util.registerOnLoadHandler(getFeed);
  </script>
  ]]>
  </Content>
</Module>

JSON の処理

JSON (JavaScript Object Notation) は、特定のタイプのオブジェクト (キー/値ペアの配列およびコレクション) を交換しやすいデータにエンコードするためのデータ交換形式です。JSON コンテンツ タイプを使用すると、JSON エンコードのコンテンツを JavaScript オブジェクトとしてフェッチできます。

下に示すガジェットは、次の JSON エンコード文字列を含むテキスト ファイルからコンテンツをフェッチします。

{"Name" : "Rowan", "Breed" : "Labrador Retriever", "Hobbies" : ["fetching", "swimming", "tugging", "eating"]}

この文字列を含むテキスト ファイルからコンテンツをフェッチすると、キー/値ペア (キーと値が結合された配列) を格納した JavaScript オブジェクトが返されます。この例ではそのオブジェクトを取得し、そこに格納されているキーと値のペアを出力します。値が配列 (角かっこ [] で示される) の場合、配列コンテンツは記号付きリストに変換されます。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Fetch JSON Example"/>
  <Content type="html">
  <![CDATA[
    <div id="content_div"></div>
    <script type="text/javascript">

    function makeJSONRequest() {    
      var params = {};
      params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
      // This URL returns a JSON-encoded string that represents a JavaScript object
      var url = "http://gadget-doc-examples.googlecode.com/svn/trunk/opensocial-gadgets/json-data.txt";
      gadgets.io.makeRequest(url, response, params);
    };

    function response(obj) { 
      var jsondata = obj.data;
      var html = "";
      // Process returned JS object as an associative array
      for (var key in jsondata) {
        var value = jsondata[key];
        html += key + ": ";
        // If 'value' is an array, render its contents as a bulleted list
        if (value instanceof Array)
        {
          html += "<br /><ul>";
          for (var i = 0; i < value.length ; i++)
          {
            html += "<li>"+ jsondata.Hobbies[i] + "</li>";
          }
          html+= "</ul>";
        }  
        // If 'value' isn't an array, just write it out as a string
        else {        
          html += value + "<br />";
        }      
      }               
      document.getElementById('content_div').innerHTML = html;
     };
     gadgets.util.registerOnLoadHandler(makeJSONRequest);
     </script>
  ]]>
  </Content>
</Module>

ガジェットの出力は次のとおりです:

Name: Rowan
Breed: Labrador Retriever
Hobbies:

  • fetching
  • swimming
  • tugging
  • eating

JSON について

Gadgets API には、オブジェクトを JSON 文字列にエンコードするための gadgets.json.stringify() メソッドと、JSON 文字列をオブジェクトに変換するための gadgets.json.parse() メソッドが用意されています。OpenSocial では、アプリケーション データを含め、返されるすべてのデータに対して自動的に HTML エスケープが実行されるため、解析前に appdata ストア内の文字列化された JSON オブジェクトをアンエスケープする必要があります。たとえば、gadgets.util.unescapeString(jsondata) のようにします。

この例では、まず JavaScript 配列を作成し、これを JSON 文字列としてエンコードしてから Array オブジェクトに変換し直しています。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="JSON Example" />
  <Content type="html">
  <![CDATA[
     <div id="content_div"></div>
     <script type="text/javascript">
     var html = "";
     // Create Array object
     var myfriends = new Array();
     myfriends[0] = "Touki";
     myfriends[1] = "Rowan";
     myfriends[2] = "Trevor";

     // Encode array as JSON string
     var jsonString = toJSON(myfriends);
     html += "The JSON string is " + jsonString + "<br />";
     html += "The type of jsonString is " + typeof(jsonString) + "<br />";

     // Convert JSON string back to an object
     var arr_obj = toObject(jsonString);
     html += "The type of arr_obj is " + typeof(arr_obj);
     document.getElementById('content_div').innerHTML = html;

     // Encode object as JSON string
     function toJSON(obj) { 
       return gadgets.json.stringify(obj); 
     }

     // Convert JSON string into an object
     function toObject(str) {
       return gadgets.json.parse(str);
    }
    </script>
  ]]>
  </Content>
</Module>

このガジェットからの出力は以下のようになります。

The JSON string is Touki","Rowan","Trevor
The type of jsonString is string
The type of arr_obj is object

認可タイプの設定

Gadgets API では、以下の認可タイプがサポートされます。

  • gadgets.io.AuthorizationType.OAUTH (コンテナは OAuth プロトコルを使用する)
  • gadgets.io.AuthorizationType.SIGNED (コンテナが要求に署名する)
  • gadgets.io.AuthorizationType.NONE (デフォルト)

これらのメソッドの使用方法は、コンテナによって異なります。Orkut の場合の署名認可タイプの使用例も参考にしてください。OAuth の使用方法について詳しくは、OAuth ガジェットの作成をご覧ください。

メソッド

makeRequest() では、HTTP GET および HTTP POST メソッドのいずれかを選択できます。

GET

通常、ウェブサイトから情報を取り出すには GET を使用します。GET は makeRequest() のデフォルト モードですが、次のように GET リクエストを明示的に作成することもできます。

function makeGETRequest(url) {
   var params = {};
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
   gadgets.io.makeRequest(url, response, params); 
};
function response(obj) {
   alert(obj.text); 
};
makeGETRequest("http://example.com"); 

GET リクエストでサーバーにパラメータを渡すには、リクエストを行うとき、クエリ文字列にパラメータを格納します。

makeGETRequest("http://example.com?param1=12345&param2=hello"); 

POST

レコードを変更または削除する目的でサーバーにデータを渡すときは通常、POST リクエストを使用します。一般に、POST リクエストでは、GET リクエストよりも大量のデータを渡すことができます。

POST は、次のようなコードを使って行います。

function makePOSTRequest(url, postdata) {
   var params = {};
   postdata = gadgets.io.encodeValues(postdata);
   params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
   params[gadgets.io.RequestParameters.POST_DATA]= postdata;
   gadgets.io.makeRequest(url, response, params); 
};
function response(obj) {
   output(obj.text); 
};
var data = {   data1 : "test",   data2 : 123456 }; 
makePOSTRequest("http://example.com", data); 

このリクエストでは opt_params で METHOD を指定するだけでなく、キー gadgets.io.RequestParameters.POST_DATA でパラメータを指定する必要があります。POST のデフォルト エンコードは application/x-www-form-urlencoded です。つまり、POST_DATA パラメータの値は、アンパサンド (&) で連結された、URL エンコードされたキー/値のペアにする必要があります。データのオブジェクトをこのフォーマットに容易に変換できるよう、gadgets.io.encodeValues という関数が用意されています。encodeValues は JavaScript オブジェクトを受け入れ、POST_DATA パラメータに一致する、エンコードされた文字列を返します。

たとえば、次のようなコードを実行した場合

var data = {   data1 : "test",   data2 : 123456 };  gadgets.io.encodeValues(data); 

次の文字列が生成されます。

data1=test&data2=123456 

この文字列は、gadgets.io.RequestParameters.POST_DATA の値として直接渡すことができます。

キャッシュの更新

makeRequest() を使用して、1 時間に複数回更新されるコンテンツ (フィード データなど) をフェッチしている場合、最新の更新を取得していない可能性があります。ガジェットの実行を速くするために、結果がキャッシュされているからです。ガジェットで必ず最新のデータを取得したい場合は、refreshInterval パラメータを使用して、キャッシュを回避し、指定した間隔で更新させることができます。つまりキャッシュは X 秒ごとに更新されます (X = refreshInterval)。

makeRequest に対する呼び出しは、デフォルトでキャッシュされます。下記の例のラッパー関数は makeRequest の呼び出しと同じパラメータを取りますが、もう 1 つ別に refreshInterval というパラメータを取ります。このパラメータを使用して、キャッシュの期間を指定できます。

function makeCachedRequest(url, callback, params, refreshInterval) {
  var ts = new Date().getTime();
  var sep = "?";
  if (refreshInterval && refreshInterval > 0) {
    ts = Math.floor(ts / (refreshInterval * 1000));
  }
  if (url.indexOf("?") > -1) {
    sep = "&";
  }
  url = [ url, sep, "nocache=", ts ].join("");
  gadgets.io.makeRequest(url, response, params);
}

キャッシュは便利な機能ですが、あまり頻繁に更新するとパフォーマンスが低下するおそれがあるので注意してください。キャッシュを行うことで、データをすばやくフェッチできるようになります。また、リモート コンテンツをホストするサードパーティ サーバーへの負荷を軽減することもできます。refreshInterval: 0 を使用すると、キャッシュが完全に無効になってしまいます。このような設定はできる限り避けてください。作成したガジェットのページ ビューが 1 日に何百万もある場合、サーバーに何百万ものリクエストを送信したり、キャッシュをオフにしたりすると、ガジェットのパフォーマンスが低下するだけでなく、ガジェットにデータを提供するサーバーの負荷が高くなりすぎます。

デフォルトではコンテンツは毎時間更新されるので、間隔を 1 時間以上に指定しては意味がありません。refreshInterval の推奨範囲は、60 以上、3600 未満です。

トップへ戻る