协议参考文档

警告:本页面介绍的是 Google 的旧版 API,即 Google 数据 API;它仅与 Google 数据 API 目录中列出的许多 API 相关,其中许多 API 已替换为较新的 API。如需了解特定新 API,请参阅新 API 的文档。如需了解如何使用较新的 API 向请求授权,请参阅 Google 帐号身份验证和授权

本文档介绍了许多 Google API 使用的 Google 数据协议,包括有关查询内容、结果内容等的信息。

如需详细了解 Google 数据协议,请参阅开发者指南概览页面和协议基础知识文档。

观众

本文适用于想要了解用于实现 Google 数据协议的 API 使用的 XML 格式和协议的详细信息。

如果您只是想编写使用这些 API 之一的代码,则无需了解这些详细信息,而可以使用特定于语言的客户端库

但如果您想了解该协议,请阅读本文档。例如,阅读本文档可以帮助您完成以下任何任务:

  • 评估 Google 数据协议架构
  • 在不使用所提供的客户端库的情况下使用协议进行编码
  • 使用新语言编写客户端库

本文档假定您了解 XML、命名空间、联合 Feed 以及 HTTP 中的 GETPOSTPUTDELETE 请求的基础知识,以及 HTTP 的“资源”概念。如需详细了解这些内容,请参阅本文档中的其他资源部分。

本文档不依赖任何特定的编程语言;您可以使用任何允许您发出 HTTP 请求并解析基于 XML 的响应的编程语言来发送和接收 Google 数据协议消息。

协议详情

本部分介绍了 Google 数据协议文档格式和查询语法。

文档格式

Google 数据协议和 Atom 具有相同的基本数据模型,即存储一些全球数据和任意数量的条目的容器。对于每种协议,格式由基本架构定义,但可以使用外部命名空间进行扩展。

Atom 是 Google 数据协议的默认格式。如需请求其他格式的响应,请使用 alt 查询参数;如需了解详情,请参阅查询请求

注意:大多数 Google 数据协议 Feed 都是采用 Atom 命名空间,通过在 Feed 元素上指定 xmlns 属性可将 Atom 命名空间用作默认命名空间,如协议基础知识中的示例所示。因此,本文档中的示例没有为 Atom 格式的 Feed 中的元素明确指定 atom:

下表显示了架构元素的 Atom 表示形式。这些表中未提及的所有数据都被视为普通 XML。除非另有说明,否则指定列中的 XML 元素均位于 Atom 命名空间中。

注意:此摘要使用标准的 XPath 表示法:具体来说,斜杠表示元素层次结构,@ 符号表示元素的属性。

在以下每个表格中,突出显示的项为必填项。

下表显示了 Google 数据协议 Feed 的元素:

Feed 架构项 Atom 表示法
Feed 标题 /feed/title
Feed ID /feed/id
Feed HTML 链接 /feed/link[@rel="alternate"]\
[@type="text/html"]/@href
Feed 说明 /feed/subtitle
Feed 语言 /feed/@xml:lang
Feed 版权 /feed/rights
Feed 作者

/feed/author/name
/feed/author/email

(某些情况下是必需的;请参阅 Atom 规范。)

Feed 上次更新日期 /feed/updated
(RFC 3339 格式)
Feed 类别 /feed/category/@term
Feed 类别架构 /feed/category/@scheme
Feed 生成器 /feed/generator
/feed/generator/@uri
Feed 图标 /feed/icon
Feed 徽标 /feed/logo

下表显示了 Google 数据协议搜索结果 Feed 的元素。请注意,该协议会在搜索结果 Feed 中公开某些 OpenSearch 1.1 响应元素

搜索结果 Feed 架构项 Atom 表示法
搜索结果数量 /feed/openSearch:totalResults
搜索结果起始索引 /feed/openSearch:startIndex
每页的搜索结果数 /feed/openSearch:itemsPerPage

下表显示了 Google 数据协议条目的各元素:

条目架构项 Atom 表示法
条目 ID /feed/entry/id
条目标题 /feed/entry/title
条目链接 /feed/entry/link
条目摘要

/feed/entry/summary

(某些情况下是必需的;请参阅 Atom 规范。)

条目内容

/feed/entry/content

(如果没有内容元素,则条目必须包含至少一个 <link rel="alternate"> 元素。)

条目作者

/feed/entry/author/name
/feed/entry/author/email

(某些情况下是必需的;请参阅 Atom 规范。)

条目类别 /feed/entry/category/@term
条目类别方案 /feed/entry/category/@scheme
参评发布日期 /feed/entry/published
(RFC 3339)
条目更新日期 /feed/entry/updated
(RFC 3339)

查询

本部分介绍如何使用查询系统。

查询模型设计原则

查询模型非常简单。基本原则如下:

  • 查询以 HTTP URI 的形式表示,而不是以 HTTP 标头或载荷的形式表示。此方法的一个好处是,您可以链接到查询。
  • 谓词的范围限定为单个项。因此,无法发送关联查询,例如“查找来自今天至少向我发送 10 封电子邮件的用户的所有电子邮件”。
  • 查询可谓词集的属性非常有限;大多数查询只是全文搜索查询。
  • 结果排序取决于实现。
  • 该协议本身就可扩展。如果您希望在服务中公开其他谓词或排序方式,可通过引入新参数轻松完成。

查询请求

客户端通过发出 HTTP GET 请求来查询 Google 服务。查询 URI 由资源的 URI(在 Atom 中称为 FeedURI)后跟查询参数组成。大多数查询参数都表示为传统的 ?name=value[&...] 网址参数。类别参数的处理方式不同,请参阅下文。

例如,如果 FeedURI 为 http://www.example.com/feeds/jo,那么您可以使用以下 URI 发送查询:

http://www.example.com/feeds/jo?q=Darcy&updated-min=2005-04-19T15:30:00Z

Google 数据协议支持 HTTP 条件 GET。实现该协议的 API 会根据返回的 Feed 或条目中的 <atom:updated> 元素值设置 Last-Modified 响应标头。客户端可以将此值作为 If-Modified-Since 请求标头的值发回,以避免在内容未发生更改时再次检索该内容。如果内容自 If-Modified-Since 以来没有变化,则服务会返回 304(未修改)HTTP 响应。

实现 Google 数据协议的 API 必须支持 alt 查询;对其他参数的支持是可选的。传递给定服务无法理解的标准参数会导致 403 Forbidden 响应。传递不受支持的非标准参数会导致 400 Bad Request 响应。如需了解其他状态代码,请参阅本文档中的 HTTP 状态代码部分。

下表汇总了标准查询参数。所有参数值都需要经过网址编码。

参数 含义 备注
alt 替代表示法类型
  • 如果您未指定 alt 参数,该服务会返回 Atom Feed。这相当于 alt=atom
  • alt=rss 会返回 RSS 2.0 结果 Feed(仅限读取)。当您以 RSS 格式请求服务数据时,该服务会提供 RSS 格式的 Feed(或其他资源表示形式)。如果给定的 Data API 属性没有对应的 RSS 属性,则该服务会使用 Atom 属性,并使用适当的命名空间来标记它,以表明它是 RSS 的扩展。
  • alt=json 会返回 Feed 的 JSON 表示法。了解详情
  • alt=json-in-script 请求将 JSON 封装在脚本标记中的响应。了解详情
  • alt=atom-in-script 请求将 XML 字符串封装在脚本代码中的 Atom 响应。
  • alt=rss-in-script 请求封装 XML 字符串的脚本响应。
  • alt=atom-service 请求描述 Feed 的 Atom 服务文档。
author 条目作者
  • 该服务会返回作者姓名和/或电子邮件地址与查询字符串匹配的条目。
category 类别查询过滤条件
  • 执行类别过滤器的另一种方法。这两种方法是等效的。
  • 如需在字词之间添加 OR,请使用竖线字符 (|),网址编码为 %7C。例如:http://www.example.com/feeds?category=Fritz%7CLaurie 会返回与任一类别匹配的条目。
  • 如需在字词之间添加 AND,请使用英文逗号 (,)。例如:http://www.example.com/feeds?category=Fritz,Laurie 会返回与这两个类别都匹配的条目。
/-/category 类别查询过滤条件
  • 以类别 /categoryname/ 的形式列出每个类别,就像它是资源 URI 的一部分一样。这是常规 name=value 格式的例外情况。
  • 请在所有其他查询参数之前列出所有类别。
  • 在第一个类别前面加上 /-/,以表明这是类别。例如,如果 Jo 的 Feed 有关于弗里茨的条目类别,您就可以按如下格式请求这些条目:http://www.example.com/feeds/jo/-/Fritz。这样,实现便可以区分类别专用查询 URI 与资源 URI。
  • 您可以列出多个类别参数(用正斜线分隔),从而查询多个类别。该服务会返回匹配所有类别的所有条目(例如,在字词之间使用 AND)。例如:http://www.example.com/feeds/jo/-/Fritz/Laurie 会返回与这两个类别都匹配的条目。
  • 如需在字词之间添加 OR,请使用竖线字符 (|),进行网址编码,编码为 %7C。例如:http://www.example.com/feeds/jo/-/Fritz%7CLaurie 会返回与任一类别匹配的条目。
  • 如果某个条目属于 Atom 规范中定义的包含匹配字词或标签的类别,则该条目将与指定类别匹配。(大致而言,“字词”是指软件用于标识类别的内部字符串,而“标签”则是指在界面中向用户显示的可人工读取的字符串。)
  • 要排除与给定类别匹配的条目,请使用 /-categoryname/ 格式。
  • 如需查询具有架构的类别(例如 <category scheme="urn:google.com" term="public"/>),您必须将该架构放在大括号中并放在类别名称前面。例如:/{urn:google.com}public。如果架构包含斜杠字符 (/),则应将其网址编码为 %2F。如需匹配没有架构的类别,请使用一对空的大括号。如果未指定大括号,则任何架构中的类别都将匹配。
  • 上述功能可以结合使用。例如:/A%7C-{urn:google.com}B/-C 表示 (A OR (NOT B)) AND (NOT C)
条目 ID 要检索的特定条目的 ID
  • 如果您指定了条目 ID,就不能再指定任何其他参数。
  • 条目 ID 的格式由服务决定。
  • 与大多数其他查询参数不同,条目 ID 是作为 URI 的一部分指定的,而不是作为 name=value 对指定的。
  • 示例:http://www.example.com/feeds/jo/entry1
fields 响应过滤条件
  • 仅返回请求的字段,而不是完整资源表示。例如:
    http://www.example.com/feeds?fields=link,entry(@gd:etag,id,updated,link[@rel='edit']))
    收到此请求后,服务器将返回仅包含 Feed 的链接和条目元素的响应。此外,返回的条目元素是仅包含 ETag、ID、update 和 edit 链接关系的部分条目。
  • 与所有查询参数值一样,字段值必须经过网址编码。
  • 如需了解详情,请参阅部分响应部分。
  • 此参数目前为实验性功能。
max-results 要检索的结果数上限 对于任何具有默认 max-results 值(限制默认 Feed 大小)的服务,如果您希望接收整个 Feed,则可以指定非常大的数字。
prettyprint 返回带有标识和换行符的 XML 响应
  • 如果为 prettyprint=true,则服务器返回的 XML 将是人类可读的(正常输出)。
  • 默认:prettyprint=false
published-minpublished-max 条目发布日期的边界
  • 使用 RFC 3339 时间戳格式。例如:2005-08-09T10:57:00-08:00
  • 下限含边界值,而上限不含边界值。
q 全文查询字符串
  • 创建查询时,请以 q=term1 term2 term3 的形式列出以空格分隔的搜索字词。(与所有查询参数值一样,空格必须经过网址编码)。该服务会返回匹配所有搜索字词的所有条目(例如在字词之间使用 AND)。与 Google 的网页搜索一样,服务会搜索完整字词(以及具有相同词干的相关字词),而不是子字符串。
  • 如需搜索完全匹配的词组,请用引号将词组括起来:q="exact phrase".
  • 如需排除与给定字词匹配的条目,请使用 q=-term 格式。
  • 搜索不区分大小写。
  • 示例:如需搜索包含完全匹配词组“Elizabeth Bennet”和字词“Darcy”但未包含字词“Austen”的所有条目,请使用以下查询:?q="Elizabeth Bennet" Darcy -Austen
start-index 要检索的第一个结果的索引(从 1 开始)
  • 请注意,这并非通用光标机制。如果您先使用 ?start-index=1&max-results=10 发送查询,然后使用 ?start-index=11&max-results=10 发送另一个查询,则该服务无法保证结果等同于 ?start-index=1&max-results=20,因为两次查询之间可能会发生插入和删除操作。
strict 严格的查询参数检查
  • 设置 strict=true 以验证服务是否能够识别每个查询参数。如果系统无法识别某个参数,系统将会返回错误。
  • 默认:strict=false
updated-minupdated-max 条目更新日期的边界
  • 使用 RFC 3339 时间戳格式。例如:2005-08-09T10:57:00-08:00
  • 下限含边界值,而上限不含边界值。
  • 在某些情况下(例如,使用日历数据 API v2.1 或更高版本时),如果指定 updated-min 过于久远,系统便会返回 HTTP 410(已删除)状态。

关于类别查询

我们决定为类别查询提供一种不同寻常的格式。您无需进行如下查询:

http://example.com/jo?category=Fritz&category=2006

我们可以使用:

http://example.com/jo/-/Fritz/2006

此方法可在不使用查询参数的情况下识别资源,并能生成更简洁的 URI。我们之所以选择类别方法,是因为我们认为类别查询是最常见的查询之一。

这种方法的缺点是,您需要在此类类别查询中使用 /-/,以便服务可以区分类别查询与其他资源 URI(例如 http://example.com/jo/MyPost/comments)。

查询响应

查询将返回 Atom Feed、Atom 条目或 RSS Feed,具体取决于请求参数。

查询结果直接在 <feed> 元素或 <channel> 元素下包含以下 OpenSearch 元素(具体取决于结果是 Atom 还是 RSS):

openSearch:totalResults
查询的搜索结果总数(不一定全部存在于结果 Feed 中)。
openSearch:startIndex
第一个结果的索引(从 1 开始)。
openSearch:itemsPerPage
每页最多可显示的内容项数。这样,客户端就可以生成指向任意一组后续网页的直接链接。不过,如需了解使用此数字的可能的误区,请参阅查询请求部分的表 start-index 注意事项。

Atom 响应 Feed 和条目还可以包含以下任意 Atom 和 Data API 元素(以及 Atom 规范中列出的其他元素):

<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="..."/>
指定用于检索整个 Atom Feed 的 URI。
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="..."/>
指定 Atom Feed 的 PostURI(可在其中发布新条目)。
<link rel="self" type="..." href="..."/>
包含此资源的 URI。type 属性的值取决于请求的格式。如果在此期间没有任何数据更改,则向此 URI 发送另一个 GET 会返回相同的响应。
<link rel="previous" type="application/atom+xml" href="..."/>
指定此查询集的上一个分块的 URI(如果分块的话)。
<link rel="next" type="application/atom+xml" href="..."/>
指定此查询集的下一个分块(如果分块了)的 URI。
<link rel="edit" type="application/atom+xml" href="..."/>
指定 Atom 条目的 EditURI(即发送已更新条目的位置)。

以下是响应搜索查询的示例响应正文:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
        xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/"
        xmlns:gd='http://schemas.google.com/g/2005'
        gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'>
  <id>http://www.example.com/feed/1234.1/posts/full</id>
  <updated>2005-09-16T00:42:06Z</updated>
  <title type="text">Books and Romance with Jo and Liz</title>
  <link rel="alternate" type="text/html" href="http://www.example.net/"/>
  <link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/>
  <link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/>
  <link rel="self" type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/>
  <author>
    <name>Elizabeth Bennet</name>
    <email>liz@gmail.com</email>
  </author>
  <generator version="1.0"
    uri="http://www.example.com">Example Generator Engine</generator>
  <openSearch:totalResults>2</openSearch:totalResults>
  <openSearch:startIndex>0</openSearch:startIndex>
  <entry gd:etag='W/"C0QBRXcycSp7ImA9WxRVGUo."'>
    <id>http://www.example.com/feed/1234.1/posts/full/4521614025009481151</id>
    <published>2005-01-09T08:00:00Z</published>
    <updated>2005-01-09T08:00:00Z</updated>
    <category scheme="http://www.example.com/type" term="blog.post"/>
    <title type="text">This is the title of entry 1009</title>
    <content type="xhtml">
      <div
        xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1009</div>
    </content>
    <link rel="alternate" type="text/html"
      href="http://www.example.com/posturl"/>
    <link rel="edit" type="application/atom+xml"
      href="http://www.example.com/feed/1234.1/posts/full/4521614025009481151"/>
    <author>
      <name>Elizabeth Bennet</name>
      <email>liz@gmail.com</email>
    </author>
  </entry>
  <entry gd:etag='W/"C0QBRXrurSp7ImA9WxRVGUo."'>
    <id>http://www.example.com/feed/1234.1/posts/full/3067545004648931569</id>
    <published>2005-01-07T08:00:00Z</published>
    <updated>2005-01-07T08:02:00Z</updated>
    <category scheme="http://www.example.com/type" term="blog.post"/>
    <title type="text">This is the title of entry 1007</title>
    <content type="xhtml">
      <div
        xmlns="http://www.w3.org/1999/xhtml">This is the entry body of entry 1007</div>
    </content>
    <link rel="alternate" type="text/html"
      href="http://www.example.com/posturl"/>
    <link rel="edit" type="application/atom+xml"
      href="http://www.example.com/feed/1234.1/posts/full/3067545004648931569"/>
    <author>
      <name>Elizabeth Bennet</name>
      <email>liz@gmail.com</email>
    </author>
  </entry>
</feed>

如果请求的 Feed 采用 Atom 格式,并且如果未指定查询参数,并且结果不包含所有条目,则会将以下元素插入顶级 Feed:<link rel="next" type="application/atom+xml" href="..."/>。它指向包含下一组条目的 Feed。后续集包含相应的 <link rel="previous" type="application/atom+xml" href="..."/> 元素。通过遵循所有下一个链接,客户端可以从 Feed 中检索所有条目。

HTTP 状态代码

下表介绍了各种 HTTP 状态代码在 Data API 环境中的含义。

编码 说明
200 OK 无错误。
201 已创建 已成功创建资源。
304 未修改 在该请求的 If-Modified-Since 标头中指定的时间之后,该资源并未发生更改。
400 请求无效 请求 URI 或标头无效,或不受支持的非标准参数。
401 未授权 需要授权。
403 已禁止 标准参数不受支持,或者身份验证或授权失败。
404 无法找到 找不到资源(例如 Feed 或条目)。
409 冲突 指定的版本号与资源的最新版本号不匹配。
410 结束 请求的更改历史记录已不在此服务器上。有关详情,请参阅特定服务的文档。
500 内部服务器错误 内部错误。这是用于所有无法识别的服务器错误的默认代码。

资源版本控制 (ETag)

有时,您需要能够引用特定条目的特定版本。

这在以下两种情况下尤为重要:

  • 执行“条件检索”,即客户端请求条目,而服务器仅在条目自客户端上次请求以来发生了更改时才发送条目。
  • 确保多个客户端不会意外覆盖彼此的更改。如果客户端为条目指定旧版本标识符,Data API 通过更新和删除操作就会失败。

Google Data API 使用 ETag(HTTP 的标准部分)来处理这两种情况。

ETag 是用于指定特定条目的特定版本的标识符。服务器将一个 ETag 附加到它向客户端发送的条目和 Feed 元素。如果条目或 Feed 发生更改,其 ETag 也会随之更改。

Google 数据 API 在两个位置提供 ETag:在 ETag HTTP 标头中,以及在 <feed><entry> 元素的 gd:etag 属性中。

在 Google Data API 中,ETag 通常是字母和数字字符串,有时还包括连字符和英文句点;该字符串通常用引号括起来。(引号是 ETag 的一部分。)例如,以下是来自 Data API 条目的 ETag:"S0wCTlpIIip7ImA0X0QI"

ETag 有两种:强和弱。强 ETag 用于标识特定条目的特定版本,可用于避免覆盖其他客户端的更改。在 Google Data API 中,弱 ETag 仅用于条件检索。弱 ETag 始终以 W/ 开头。例如 W/"D08FQn8-eil7ImA9WxZbFEw."

并非所有 Google Data API 都支持强大的 ETag。如果是这样,则安全系数高的 ETag 仅用于条目;Feed 中的 ETag 弱。

以下示例展示了从支持强 ETag 的服务检索到的 Feed(包括部分 HTTP 标头):

GData-Version: 2.0
ETag: W/"C0QBRXcycSp7ImA9WxRVFUk."
...
<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
    xmlns:gd='http://schemas.google.com/g/2005'
    gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'>
  ...
  <entry gd:etag='"CUUEQX47eCp7ImA9WxRVEkQ."'>
    ...
  </entry>
</feed>

支持版本 2 数据 API 的客户端库将以透明的方式为您处理 ETag。以下信息适用于不使用客户端库的客户端,以及有兴趣在协议一级处理版本控制的读者。

注意:如需了解 Data API 1.0 版中使用的资源版本控制系统,请参阅 1.0 参考指南

条件检索

如果要检索以前检索过的条目,您可以通过让服务器发送自上次检索后更改的条目来提高效率。

要进行此类条件检索,请发送包含 HTTP If-None-Match 标头的 HTTP GET 请求。在标头中,指定条目的 ETag。

以下是 If-None-Match 标头的示例:

If-None-Match: W/"D08FQn8-eil7ImA9WxZbFEw."

服务器收到此请求后,会检查您所输入的条目是否与您指定的 ETag 相同。如果这些 ETag 匹配,则表示相应条目未发生变化,且服务器会返回 HTTP 304 Not Modified 状态代码。

如果两个 ETag 不匹配,则该条目自您上次请求后已被修改,服务器将返回该条目。

更新条目

要避免覆盖其他客户端的更改,最简单的方法就是让服务器确保当客户端发送更新后的条目时,客户端启动的条目版本与服务器存储的当前版本相同。如果第二个客户端先于客户端进行更新,则客户端的更新将被拒绝,因为客户端不再基于最新版本的修改。

当您的客户端从支持强 ETag 的服务检索数据时,每个条目都有一个 ETag,用于充当该条目版本的唯一版本标识符。

注意:使用 ETag 进行更新仅适用于强大的 ETag。对于提供弱 ETag 的服务,所有更新都会成功,而不管其他人是否在您检索到条目之后更新了相应条目;最新的更新始终会覆盖任何其他之前的更新。因此,请勿在更新或删除时发送较弱的 ETag。否则,您会收到错误消息。

因此,当客户端向 strong-ETag 服务发送更新时,需要指定所更新条目的版本。为此,您可以采用以下两种方法:

  • 使用 If-Match HTTP 标头。
  • <atom:entry> 元素中使用 gd:etag 属性。

我们建议尽可能使用 If-Match 方法。

如需使用 If-Match 更新条目,请先获取要更新的条目。根据需要修改条目,然后创建包含修改后的条目的新 PUT 请求。(有关要使用的网址的详细信息,请参阅特定服务的文档。)

在发送 PUT 之前,请添加包含原始条目中的 ETag 的 HTTP If-Match 标头:

If-Match: "S0wCTlpIIip7ImA0X0QI"

然后发送 PUT 请求。

如果更新成功,服务器将返回 HTTP 200 OK 状态代码以及更新后的条目的副本。

如果由于您指定的 ETag 与条目中的当前 ETag 不匹配(这意味着该条目自上次检索以来在服务器上发生更改)而更新失败,服务器将返回 HTTP 412 Precondition Failed 状态代码。

如果无法轻松编写 HTTP 标头,或者因其他原因需要避免使用 If-Match 标头,您可以改为使用 gd:etag 属性。

如果您不发送 If-Match 标头,则服务器会将更新后的条目的 gd:etag 属性值用作隐式 If-Match 值。

要替换版本控制系统并更新该条目(无论自您检索以来是否有其他人更新了该条目),请使用 If-Match: * 而不是在标头中指定 ETag。

如需了解哪些服务支持增强型 ETag,请参阅迁移指南

删除条目

删除使用强 ETag 的条目与更新它们非常相似。

如需删除具有强 ETag 的条目,请先检索要删除的条目,然后向该条目的编辑网址发送 DELETE 请求。

如果您想确保自己删除的条目在检索后已被其他客户端更改,请添加包含原始条目 ETag 值的 HTTP If-Match 标头。

如果您希望覆盖版本控制系统并删除该条目(无论自您检索以来是否有其他人更新了该条目),请使用 If-Match: * 而不是在标头中指定 ETag。

如果某个条目没有强 ETag,则 DELETE 请求会始终成功。

部分响应(实验性)

默认情况下,服务器在处理完请求后会发回目标资源的完整表示形式。部分响应允许您仅请求感兴趣的元素或属性,而不是请求完整的资源。这让您的客户端应用可以避免传输、解析和存储不需要的字段,因此可以更高效地使用网络、CPU 和内存资源。

如需了解您使用的产品是否有部分响应,请参阅其 API 文档。

如需请求部分响应,请使用 fields 查询参数指定您希望返回的元素或属性。示例如下:

http://www.example.com/feeds?fields=link,entry(@gd:etag,id,updated,link[@rel='edit']))

服务器的响应仅包含 Feed 的链接和条目元素;条目元素仅包含 ETag、ID、已更新和修改链接信息。以下部分介绍了 fields 查询参数语法。如需详细了解响应,请参阅处理部分响应

注意:您可以对返回数据的任何请求使用 fields 查询参数。除了 GET 之外,还包含 POSTPUT(以及用于进行部分更新PATCH)。不过,fields 查询参数只会影响响应数据,不会影响您必须提供的数据或者更新或创建的字段。

fields 参数语法摘要

fields 查询参数值的格式基于 XPath 语法;不过,它仅支持一部分有效 XPath 表达式。以下内容对受支持的语法进行了总结。如需了解更多示例,请参阅下一部分。

  • 使用逗号分隔列表来选择多个字段。
  • 使用 a/b 选择嵌套在元素 a 内的元素 b;使用 a/b/c 选择嵌套在 b 内的元素 c
  • 使用 '@' 前缀标识具有给定名称的属性;省略 '@' 前缀以引用元素。
  • 应用字段条件以选择符合特定条件的元素,方法是在要限制的元素后面添加表达式“[ ]”。

    例如,fields=entry[author/name='Elizabeth'] 仅返回伊丽莎白是作者的 Feed 条目。

  • 通过将表达式放在任何所选元素后面的圆括号“( )”中,可指定字段子选择器,以便仅请求特定属性或子元素。

    例如,fields=entry(id,author/email) 只会返回每个 Feed 条目的 ID 和作者的电子邮件地址。

  • 您可以使用英文双引号或单引号分隔字符串

    要转义英文双引号或单引号,请重复该引号。例如,"""Hello,"" he said" 会生成字符串 "Hello," he said'''Hello,'' he said' 会生成字符串 'Hello,' he said
  • 您可以在字段选择中使用通配符。

    例如,entry/gd:* 会选择 gd 命名空间中的所有条目子元素,entry/@gd:* 会选择同一命名空间中的子元素属性。

fields 查询参数充当输出过滤条件。这意味着,系统仅在处理查询的其余部分之后才会计算部分响应。例如,如果您还指定了 max-results 查询参数来指明每页需要 20 个结果,则系统会生成前 20 个结果,并根据得出的部分计算结果。如果 fields 规范与查询选择的前 20 个条目中的任何一项都不匹配,则会返回空的 Feed;您不会获得返回的前 20 个条目。

注意:请勿尝试将字段条件用作查询选择器。也就是说,不要试图检索完整的 Feed 并应用字段条件从非常大的数据集中滤除相关项。尽可能使用其他查询参数(如 start-indexmax-results)将每个查询的结果缩减为便于管理的大小。否则,因使用不当而导致严重的性能下降可能会抵消部分响应所带来的性能提升。

设置 fields 参数值的格式

以下准则介绍了如何构造 fields 查询参数值。每条准则都包含示例,并提供了有关参数值如何影响响应的说明。

注意:与所有查询参数值一样,fields 参数值也必须采用网址编码。为便于阅读,下面的示例省略了编码。

确定您希望返回的字段,或者进行字段选择
fields 查询参数值是以逗号分隔的元素或属性列表(统称为“字段”),并且每个字段都是相对于资源表示形式的根元素指定的。因此,如果您要检索 Feed,则字段是相对于 <feed> 元素指定的;如果您要检索单个条目,则字段是相对于 <entry> 元素指定的。如果您选择的元素是(或属于)Feed 中的一个重复元素,该服务会返回该元素的所有实例。

下面是一些 Feed 级示例:
示例 效果
entry 返回所有 <entry> 元素以及这些条目的所有子元素,但不返回 <feed> 的其他任何子元素。
id,entry 返回 Feed <id> 和所有 <entry> 元素。
entry/title 返回所有 Feed 条目的 <title> 元素。

每当返回嵌套元素时,响应中均会包含 父元素的封闭标记。父级标记不会包含任何其他子元素或属性,除非还明确选择了它们。
entry/author/uri 仅返回所有 Feed 条目的 <author> 元素的 <uri> 子元素。
entry/*:rating 对于所有 Feed 条目,在任何命名空间中仅返回本地名称为 rating 的子元素。

下面是一些入门级示例:
示例 效果
author 返回目标条目的 <author> 子元素。
@gd:etag 返回目标条目的 etag 属性。
author/uri 返回目标条目的 <author> 元素的 <uri> 子元素。
media:group/media:* 返回目标条目的 media 命名空间中 <media:group> 的所有子字段。
仅限所选字段符合特定条件,或者使用字段条件
默认情况下,如果您的请求指定某个元素多次发生,则部分响应将包括该元素的所有实例。不过,您还可以指定响应应仅包含具有特定属性值的元素,或使用“[ ]”语法满足某些其他条件的元素,如以下示例所示。如需了解详情,请参阅字段条件语法部分。
示例 效果
entry[link/@rel='edit'] 返回 rel 属性值为 'edit'<link> 元素的所有 Feed 条目。
entry/title[text()='Today'] 返回 Feed 条目中发生的任何 <title> 元素(如果其内容为 'Today')。
entry/author[name='Jo'] 如果 Feed 条目中含有内容为 'Jo'<name> 子元素,则返回这些 <author> 元素。
author[name='Jo'] 如果目标条目中的 <name> 子元素包含内容 'Jo',则返回目标条目中的 <author> 元素。
仅请求部分选定元素,或使用字段子选择
默认情况下,如果您的请求指定特定元素,该服务会完整地返回这些元素。您可以指定响应应仅包含所选元素中的特定子元素。如下例所示,您可以使用“( )”子选择语法来实现此目的。
示例 效果
entry/author(uri) 仅返回 Feed 条目中作者的 <uri> 子元素。
entry/author[name='Jo'](uri) 对于作者名称为 'Jo' 的任何条目,仅返回 <author><uri> 子元素。
entry(link(@rel,@href)) 仅返回 Feed 条目中每个 <link> 元素的 relhref 属性的值。
entry(title,link[@rel='edit']) 仅返回具有每个 Feed 条目的修改 rel 属性的 <title><link> 元素。
entry(title,author(uri) 为每个 Feed 条目返回 <title> 元素和作者 <uri> 元素。

详细了解字段条件语法

您可以对字段或子字段使用字段条件。如果条件为 true,则所选字段将包含在结果中。如果没有字段条件,则会包含所选类型的所有字段。

所选字段的文本值用于比较。在这种情况下,如果字段是元素,则文本值是其内容;如果字段是属性,则文本值是该属性的值。如果该字段没有文本值,则比较会失败,并且该字段不包含在结果中。

下表显示了字段条件支持的 XPath 运算符,并提供了一些示例。

运营商 语法 示例
字符串比较

=eq
!=ne

  • 返回整个条目(如果其中包含 <link> 元素,该元素具有设为“self'”的 rel 属性):
        entry[link/@rel='self']

  • 如果 <title> 元素的内容等于字符串 'unknown',则返回整个条目:
        entry[title eq 'unknown']

  • 如果内容不是 'unknown',则返回整个 <title> 元素:
        title[text() != 'unknown']
逻辑比较 and
or
not
  • 返回属性 rel 设置为 'self''edit' 的所有链接:
        link[@rel='self' or @rel='edit']

  • 返回属性 rel 设置为 'self' 且属性 type 设置为 'application/atom+xml' 的所有链接:
        link[@rel='self' and @type='application/atom+xml']

  • 返回没有值 'self' 属性 rel 的任何链接:
        link[not(@rel='self')]

    请注意,与 XPath 一样,not 也看起来像函数调用。
数值比较 =eq
!=ne
>gt
>= 或 ge
<lt
<=le
  • 返回任何具有 value 属性且可转换为整数 5 的 <gd:rating> 元素:
        gd:rating[@value=5]

  • 返回任何具有 average 属性且可转换为大于 4.3 的浮点数的 <gd:rating> 元素:
        gd:rating[@average gt 4.3]
日期比较 使用数值比较运算符,如示例所示。

如需比较日期或日期/时间,您可以将元素、属性或字符串字面量转换为 xs:datexs:dateTime。对于 xs:dateTime,默认时区为世界协调时间 (UTC),但最好明确指定时区。

  • 返回包含 2005 年 1 月 1 日以来的日期的所有 <yt:recorded> 元素:
        yt:recorded[xs:date(text())>=xs:date('2005-01-01')]

  • 返回在指定时间(以 UTC 时区指定)之后更新的所有条目:
        entry[xs:dateTime(updated)>xs:dateTime('2008-07-25T08:19:37.549Z')]
存在

使用元素或属性的名称,如示例所示。

  • 返回包含具有属性 rel 的链接的所有条目:
        entry[link/@rel]

  • 返回具有名为 value 的任何 <gd:rating> 元素:
        entry/gd:rating[@value]
Boolean true()
false()

布尔值在测试期间非常有用,可将字段条件强制设置为 true 或 false 状态。

  • 返回所有 <link> 元素:
        link[true()]

处理部分响应

支持部分响应的服务器处理完包含 fields 查询参数的有效请求之后,会发回 HTTP 200 OK 状态代码以及所请求的属性或元素。如果 fields 查询参数出现错误或因其他原因而无效,服务器将返回 HTTP 400 Bad Request 状态代码。

响应的根元素是 <feed><entry>,具体取决于目标 URI。根元素的内容仅包含该 Feed 或条目的所选字段,以及所有父元素的封闭标记。

可通过以下两种方式回放请求的 fields 查询参数

  • 根元素具有 gd:fields 属性,用于显示请求中指定的 fields 查询参数的值。
  • 如果目标 URI 是 Feed,则每个可修改的条目都有一个 gd:fields 属性,用于显示适用于它的 fields 选择部分。

注意:为了在部分响应中看到这些 gd:fields 属性值,您必须将它们包含在 fields 查询参数规范中。您可以通过使用 @gd:fields 或更通用的 @gd:*(其中也包含 ETag 信息)来显式执行此操作。

以下示例查询要求服务器返回仅包含 gd 命名空间中属性(Feed 级别和入门级别)的文档,以及每个 ID 条目的 Feed ID、标题和修改链接。

http://example.com/myFeed?fields=@gd:*,id,entry(@gd:*,title,link[@rel='edit'])

服务器会返回以下部分响应以及 200 Successful HTTP 状态代码:

<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
    xmlns:gd='http://schemas.google.com/g/2005'
    gd:etag='W/"DEAEQH47eCp7IWA9WxBVGUo."'
    gd:fields='@gd:*,id,entry(@gd:*,title,link[@rel='edit'])>
  <id>http://example.com/myFeed</id>
  <entry gd:etag='"EksPTg1Bfyp7IWA6WhJT"'
      gd:fields="@gd:*,title,link[@rel='edit']">
    <link rel='edit' href='http://example.com/myFeed/1/'/>
    <title>This year</title>
  </entry>
  <entry gd:etag='"EksPQA1Cdyp7IWA6WhJT"'
      gd:fields="@gd:*,title,link[@rel='edit']">
    <link rel='edit' href='http://example.com/myFeed/2/'/>
    <title>Last year</title>
  </entry>
  <entry d:etag='"EksPQAxHeCp7IWA6WhJT"'
      gd:fields="@gd:*,title,link[@rel='edit']">
    <link rel='edit' href='http://example.com/myFeed/3/'/>
    <title>Today</title>
  </entry>
</feed>

如果所选字段不匹配,服务仍会返回 200 Successful HTTP 状态代码,但部分响应是空 Feed:

<?xml version='1.0' encoding='utf-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
  xmlns:gd='http://schemas.google.com/g/2005'
  gd:etag='W/"DEAEQH47eCp7IWA9WxBVGUo."'
  gd:fields='@gd:*,id,entry(@gd:*,title,link[@rel='edit'])>
</feed>

部分更新(实验性)

如果 Google 产品支持部分响应和可编辑资源,您还可以使用部分更新。使用部分更新时,您可以只发送要更新的字段,而不是发送完整资源表示法的修改版本。这样可以让您的客户端应用在使用更新以及使用部分响应检索数据时更加高效。

但是,在进行部分更新时,您必须使用 PATCH 请求,而不是 PUTPATCH 的语义非常强大,可让您通过单个请求添加、替换和删除特定条目的特定字段。

如需了解您当前使用的产品是否有部分更新,请参阅特定产品的文档。

提交部分更新请求

如需提交部分更新请求,请向您通常使用 PUT 更新资源时所用的网址发送 HTTP PATCH 请求。PATCH 请求的正文是一个 <entry> 元素,用于指定要添加或修改的字段。该条目的 gd:fields 属性表示您想删除的字段。

服务器以特定顺序处理 PATCH 请求:

  1. 它首先从资源表示中移除 gd:fields 属性指定的字段。

    gd:fields 属性的语法与请求部分响应时使用的 fields 查询参数相同。有关详情,请参阅支持的语法

  2. 然后,它会合并到表示正文中提供的数据的现有资源。

    如需详细了解如何合并数据,请参阅下文的添加或更新字段

注意:由于 PATCH 请求的正文通常不符合 Atom 整合格式,因此您在 PATCH 请求中使用的 Content-Typeapplication/xml

以下是部分更新请求的示例:

PATCH /myFeed/1/1/
Content-Type: application/xml

<entry xmlns='http://www.w3.org/2005/Atom'
    xmlns:gd='http://schemas.google.com/g/2005'
    gd:fields='description'>
  <title>New title</title>
</entry>

PATCH 请求会对目标 URI 条目在服务器上存储的资源表示法进行以下更改:

  • 移除 <description> 元素。
  • 更新 <title> 元素。

部分更新请求的语义

以下说明介绍了如何设置 PATCH 请求以删除、添加或更新条目内的特定字段。单个 PATCH 请求可以执行这些操作的任意组合。

  • 删除字段。使用 <entry> 元素的 gd:fields 属性来标识要从资源中删除的所有字段。以下示例请求会删除与条目关联的标题和摘要。不过,该请求不会为相应条目添加或更新任何其他数据。

    PATCH /myfeed/1/1/
    Content-Type: application/xml
    
    <entry xmlns='http://www.w3.org/2005/Atom'
        xmlns:gd='http://schemas.google.com/g/2005'
        gd:fields='title,summary'/>
    
  • 添加或更新字段。使用 <entry> 元素的正文指定要为资源添加或更新的数据。执行以下任一删除操作后,这些字段将合并到资源的现有数据中:

    • 系统会添加尚未显示的字段。如果资源数据尚未为某个字段指定值,则该字段会添加到现有数据中。例如,如果某个条目没有标题,而您的 PATCH 请求包含 <title> 元素,则系统会将新标题添加到该条目中。

    • 已替换或附加已存在的字段。合并资源数据中已指定的字段的具体行为取决于字段的特征:

      • 非重复字段会被替换。如果资源数据已指定非重复元素的值,则您在 PATCH 请求中指定的值会替换该元素的现有值。例如,在下面的示例中,新标题将取代现有标题。

        PATCH /myFeed/1/1/
        Content-Type: application/xml
        
          <entry xmlns='http://www.w3.org/2005/Atom'
            xmlns:gd='http://schemas.google.com/g/2005'>
          <title>New Title</title>
        </entry>

        下面给出了一个更复杂的示例。在此示例中,假设该条目只能有一个作者,并且目标资源已经具有作者姓名和电子邮件地址的值。尽管 <author> 元素有两个子字段,但提供的数据中仅包含 <name> 元素。因此,只有该字段的值会被覆盖。所提供的数据中缺少 <email> 元素的值,该值保持不变。

        PATCH /myfeed/1/1/
        Content-Type: application/xml
        
        <entry xmlns='http://www.w3.org/2005/Atom'
            xmlns:gd='http://schemas.google.com/g/2005'>
          <author>
            <name>New Name</name>
          </author>
        </entry>
      • 附加了重复字段。如果资源数据已指定重复元素的值,那么您提供的新元素将添加到现有的一组值中。

        请注意,除了添加重复元素的新实例之外,您可能还希望执行其他操作。例如,您可能想要执行以下操作之一:

        • 替换整个重复元素列表。您可以使用 gd:fields 属性(例如 gd:fields='ns:accessControl')删除所有重复字段,并提供一整套替换字段。由于所有现有元素首先被删除,因此您提供的这组字段在附加时不会与任何现有值冲突。

        • 替换某个重复元素的一组现有值中的一个值。在这种情况下,只需定义足够具体的 gd:fields 值即可移除单个元素,避免删除您想要保留的其他值。例如,如需仅移除 actionembed 的访问权限控制,您可以使用 gd:fields='ns:accessControl[@action="embed"]'。然后,在 <entry> 元素的正文中提供要将其替换的单个字段:

          PATCH /myfeed/1/1/
          Content-Type: application/xml
          
          <entry xmlns='http://www.w3.org/2005/Atom'
              xmlns:gd='http://schemas.google.com/g/2005'
              gd:fields='ns:accessControl[@action="embed"]>
            <ns:accessControl action="embed" permission="allowed" />
          </entry>

处理对部分更新的响应

处理完有效的部分更新请求后,API 会返回 200 OK HTTP 响应代码。默认情况下,响应的正文是您更新的完整条目。服务器会在成功处理 PATCH 请求时更新 ETag 值,就像处理 PUT 一样。

如果 PATCH 请求导致的新资源状态在语法或语义上是无效的,则服务器会返回 HTTP 400 Bad Request422 Unprocessable Entity HTTP 状态代码,并且资源状态会保持不变。例如,如果您尝试删除必填字段,但没有提供替代字段,则服务器会返回错误。

注意:了解不同字段之间的关系非常重要。仅更新部分相互依赖的值可能会使资源进入不一致状态。例如,可将开始时间更新为晚于结束时间的值。虽然该 API 应返回错误代码,但我们建议您全面测试这些条件,以确保一致性。

不支持 PATCH 时的备用表示法

如果您的防火墙不支持 PATCH,请发出 HTTP POST 请求并将替换标头设置为 PATCH,如下所示:

POST /myfeed/1/1/
X-HTTP-Method-Override: PATCH
Content-Type: application/xml
...

使用部分响应和部分更新

您可以将部分响应用作后续部分更新请求的基础。如果您这样做,请指定包含修改链接的 fields 查询参数,以及 @gd:*。这样可确保部分响应包含 ETag 和 gd:fields 属性值等信息,这对后续请求非常重要。

以下示例返回了部分响应,您可以将其作为未来部分更新的基础:

http://example.com/myFeed/1/1/?fields=@gd:*,link[@rel='edit'](@href),gd:who

服务器做出以下响应:

<?xml version='1.0' encoding='utf-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'
    xmlns:gd='http://schemas.google.com/g/2005'
    gd:etag='"E0UKRAREeCp7IWA6WhJT"'
    gd:fields="@gd;*,link[@rel='edit'](@href),gd:who">
  <link href='http://example.com/myFeed/1/1/'/>
  <gd:who email='liz@gmail.com'/>
  <gd:who email='jo@gmail.com'/>
  <gd:who email='jane@gmail.com'/>
</entry>

假设您想移除电子邮件地址为 'jane@gmail.com' 的用户,添加电子邮件地址为 'will@gmail.com' 的用户,并将当前列为 'jo@gmail.com' 的用户的电子邮件地址更改为 'josy@gmail.com'

您可以执行这些更改,只需从上一个响应的结果开始,仅修改不同的字段,然后将修改后的部分条目作为 PATCH 请求的正文提交。对于此示例,所需的修改如下:

  • 从提供的元素列表中删除 <gd:who email='jane'/>
  • <gd:who email='will@gmail.com'/> 添加到提供的元素列表中。
  • <gd:who email='jo@gmail.com'/> 替换为 <gd:who email='josy@gmail.com'/>

基于部分响应的 PATCH 请求如下所示:

PATCH /myFeed/1/1/
Content-Type: application/xml

<entry gd:fields="@gd:*,link[@rel='edit'](@href),gd:who"
    gd:etag="FE8LQQJJeSp7IWA6WhVa">
  <link href='http://example.com/myFeed/1/1'/>
  <gd:who email='liz@gmail.com'/>
  <gd:who email='josy@gmail.com'/>
  <gd:who email='will@gmail.com'/>
</entry>

注意:此方法依赖于条目的部分响应中包含的 gd:fieldsgd:etag 属性(如果支持)。除了您明确要移除的字段之外,部分条目的正文必须保留部分响应中的所有字段和属性。您可以使用新值更新正文中的任何现有字段,还可以添加要添加的任何新字段。

身份验证

当客户端尝试访问服务时,可能需要向服务提供用户的凭据,以证明用户有权执行相关操作。

客户端应该使用何种身份验证方法取决于客户端类型:

在 EGL 系统中,桌面客户端要求用户提供其凭据,然后将这些凭据发送到 Google 身份验证系统。

如果身份验证成功,则身份验证系统会返回一个令牌,该客户端随后会在发送 Data API 请求时使用该令牌(在 HTTP 授权标头中)。

如果身份验证失败,服务器将返回 403“禁止访问”状态代码,以及包含适用于身份验证的质询的 WWW-Authenticate 标头。

AuthSub 系统的工作方式类似,只不过它不是要求用户提供凭据,而是将用户连接到请求凭据的 Google 服务。然后,该服务会返回 Web 应用可以使用的令牌;这种方法的优势在于,Google(而不是 Web 前端)可以安全地处理和存储用户的凭据。

要详细了解这些身份验证系统,请参阅 Google 数据 API 身份验证概览Google 帐号身份验证文档。

会话状态

许多业务逻辑实现都需要会话粘性,即跟踪用户会话的状态。

Google 通过以下两种方式跟踪会话状态:使用 Cookie,使用可作为查询参数发送的令牌。这两种方法可实现相同的效果。我们建议客户支持下列任一会话状态跟踪方法(两种方法足以满足需求)。如果客户端不支持其中任一方法,则该客户端仍可使用 Data API,但与支持这些方法的客户端相比,性能可能会受影响。具体而言,如果客户端不支持这些方法,那么每个请求都会产生重定向,因此每个请求(及任何关联数据)都会发送到服务器两次,这会影响客户端和服务器的性能。

Google 客户端库会处理会话状态,因此如果您使用我们的库,则无需执行任何操作即可获得会话状态支持。

其他资源

以下第三方文档可能对您有所帮助:

返回页首