URI Conventions (OData Version 2.0)
OData Version 4.0是当前推荐的OData版本。OData V4已经由OASIS进行了标准化,并且具有许多OData Version 2.0中没有包含的特性。
Introduction
开放数据协议(OData)支持创建基于rest的数据服务,它允许使用统一资源标识符(uri)标识并在数据模型中定义的资源由Web客户端使用简单的HTTP消息发布和编辑。本规范定义了一组推荐的(但不是必需的)规则,用于构造URI以标识OData服务器公开的数据和元数据,以及一组保留的URI查询字符串操作符,如果OData服务器接受,则必须实现这些操作符。
[OData:Atom]和[OData:JSON]文档指定了使用OData交换的资源表示的格式,[OData:Operations]文档描述了可以在uri上执行的操作(可以根据本文定义的约定构造)文档)嵌入在这些表示中。
鼓励服务器尽可能遵循本规范中定义的URI构造约定,因为这种一致性促进了可重用客户端组件和库的生态系统。
本文档中使用的术语在[OData:Terms]文档中定义。
1. URI Components
OData服务使用的URI最多有三个重要部分:服务根URI,资源路径和查询字符串选项。额外的URI结构(如片段)可能存在于OData服务使用的URI中;但是,本规范对此类附加结构没有进一步的含义。
下面是两个uri示例,它们被分解为它们的组成部分:
2. Service Root URI
服务根URI标识OData服务的根。由这个URI标识的资源必须是一个AtomPub服务文档(如[RFC5023]中指定的),并遵循AtomPub服务文档的OData约定(如果请求不同的格式,则使用Atom服务文档的替代表示)。OData: JSON格式指定了服务文档的这种基于JSON的替代表示形式。需要从OData服务的根返回服务文档,以便为客户机提供一种简单的机制来枚举数据服务可用的所有资源集合。
Example Request URI | OData Service URI |
---|---|
https://services.odata.org:8080 | https://services.odata.org:8080 |
https://services.odata.org/OData/OData.svc/Categories | https://services.odata.org/OData/OData.svc/ |
3. Resource Path
本节定义的资源路径构造规则是可选的。鼓励OData服务器遵循URI路径构造规则(除了必需的查询字符串规则之外),因为这种一致性促进了可重用客户端组件和库的丰富生态系统。
URI的资源路径部分标识要与之交互的资源(例如客户、单个客户、与伦敦客户相关的订单,等等)。资源路径支持对OData服务公开的数据模型的任何方面(条目集合、单个条目、属性、链接、服务操作等)进行寻址。
3.1. Addressing Entries
对Collection (of Entries)、Collection中的单个Entry以及Entry的属性进行寻址的基本规则如下图所示。
- Collection: 服务公开的集合或服务操作(它返回条目集合)的名称。
- KeyPredicate: 标识条目的关键属性值的谓词。如果条目只有一个key Property,谓词可以只包含key Property的值。如果键由两个或多个属性组成,则必须使用名称/值对声明其值。更准确地说,KeyPredicate的语法如下图所示。
- NavPropSingle: 由与先前路径段关联的条目定义的导航属性的名称。Navigation属性必须标识单个实体(即具有“to 1”关系)。
- NavPropCollection: 与NavPropSingle相同,除了它必须标识条目的集合(也就是说,具有“对多”关系)。
- ComplexType: 与先前路径段关联的条目或复杂类型的声明属性或动态属性的名称。
- Property: 与先前路径段关联的条目或复杂类型的声明属性或动态属性的名称。
对于符合本节中的寻址约定的OData服务,通过向服务根URI添加单个路径段来形成标识单个条目的绝对URI的规范形式。路径段由与条目相关联的集合的名称组成,后面跟着标识集合中的条目的键谓词。例如,uri https://services.odata.org/OData/OData.svc/Categories(1)/Products(1)和https://services.odata.org/OData/OData.svc/Products(1)。
Examples
参考服务及其服务元数据文档available,位于https://services.odata.org/OData/OData.svc/和https://services.odata.org/OData/OData.svc/$metadata。
https://services.odata.org/OData/OData.svc/Categories
- 标识所有类别集合。
- 由服务元数据文档中名为“Categories”的实体集描述。
https://services.odata.org/OData/OData.svc/Categories(1)
- 标识一个键值为1的类别条目。
- 由服务元数据文档中名为“Categories”的实体类型描述。
https://services.odata.org/OData/OData.svc/Categories(1)/Name
- 标识键值为1的Categories条目的Name属性。
- 由服务元数据文档中“Categories”实体类型上名为“Name”的属性描述。
https://services.odata.org/OData/OData.svc/Categories(1)/Products
- 标识与键值为1的Category Entry相关联的product集合。
- 由服务元数据文档中“Categories”实体类型上名为“Products”的导航属性描述。
https://services.odata.org/OData/OData.svc/Categories(1)/Products/$count
- 标识与类别1相关联的产品条目的数量。
- 由服务元数据文档中“Categories”实体类型上名为“Products”的导航属性描述。
https://services.odata.org/OData/OData.svc/Categories(1)/Products(1)/Supplier/Address/City
- 标识与类别1相关联的产品1的供应商所在城市。
- 由服务元数据文档中“Address”复合类型上名为“City”的属性描述。
https://services.odata.org/OData/OData.svc/Categories(1)/Products(1)/Supplier/Address/City/$value
- 与上面的URI相同,但标识City属性的“raw value”。
3.2. Addressing Links between Entries
与在Web页面上使用链接非常相似,OData服务使用的数据模型支持将关系作为第一类构造。例如,OData服务可以公开一个产品条目集合,每个产品条目都与一个类别条目相关。
条目之间的关联在OData中可以寻址,就像条目本身一样(如上所述)。处理关系的基本规则如下图所示。
- NavigationProperty: 在与“$links”段之前的路径段相关联的条目中声明的导航属性的名称。
Examples
下面的示例uri遵循上述寻址规则,并基于参考服务及其在https://services.odata.org/OData/OData.svc/和https://services.odata.org/OData/OData.svc/$metadata上提供的服务元数据文档。
https://services.odata.org/OData/OData.svc/Categories(1)/$links/Products
- 标识与类别1相关的一组产品。
- 由相关服务元数据文档中“Categories”实体类型上名为“Products”的导航属性描述。
https://services.odata.org/OData/OData.svc/Products(1)/$links/Category
- 标识与产品1相关的类别。
- 由相关服务元数据文档中“产品”实体类型上名为“Categories”的导航属性描述。
3.3. Addressing Service Operations
OData服务可以公开服务操作,与条目一样,服务操作使用URI进行标识。服务操作是由OData服务公开的简单函数,其语义由函数的作者定义。Service Operation可以接受原语类型输入参数,并且可以定义为返回单个原语、单个复杂类型、原语集合、复杂类型集合、单个条目、条目集合或空。构造uri以寻址服务操作并向其传递参数的基本规则如下图所示。
- ServiceRootUri: service root URI标识OData服务的根。
- ServiceOperation: 由OData服务公开的服务操作的名称。
- ParamName: 服务操作接受的参数名称。如果服务操作接受多个参数,则URI查询字符串中参数的顺序无关紧要。
- ParamValue: 参数的值。值的格式由[OData:Core] (OData概述规范)的Abstract Types部分中的表的文字形式列定义。
Examples
下面的示例uri遵循上述寻址规则,并基于参考服务及其在https://services.odata.org/OData/OData.svc/和https://services.odata.org/OData/OData.svc/$metadata上提供的服务元数据文档。
https://services.odata.org/OData/OData.svc/ProductsByColor?color=‘red’
- 标识ProductByColor服务操作并向其传递一个字符串参数。由于服务操作只是函数,因此它们的语义取决于函数的实现者。在本例中,Service Operation返回所有红色product。
- 由名为“ProductsByColor”的函数导入描述,该函数在服务元数据文档中接受一个名为“color”的字符串参数。
https://services.odata.org/OData/OData.svc/ProductsByColor(3)/Category/Name?color='red’
- 标识与上面示例相同的函数;但是,由于该函数返回条目集合(这里是product),因此它充当伪集合,因为附加的路径段可能会跟随由服务操作标识的伪集合中的条目的标识条目或链接。在这种情况下,函数的结果被视为项的集合,如前面的寻址项部分所述。
- 在服务元数据文档中描述为:
- 函数导入名为“ProductsByColor”,它接受一个名为“color”的字符串参数。
- “Product”实体类型上的“Category”导航属性。
- “Category”实体类型上的“Name”属性。
https://services.odata.org/OData/OData.svc/ProductsByColor?color=‘red’¶m=foo
- 与下面的示例相同,只是指定了一个额外的参数(param)。由于该函数没有定义名为param的输入参数,因此该参数将被忽略,并且不被视为函数调用的一部分。
https://services.odata.org/OData/OData.svc/ProductColors
- 标识不接受参数的ProductColors服务操作。
- 由服务元数据文档中名为“ProductColors”的函数导入描述。这个函数返回一个字符串集合。
4. Query String Options
OData URI的“查询选项”部分指定了三种类型的信息:系统查询选项、自定义查询选项和服务操作参数。所有OData服务都必须遵循本节及其子节中定义的查询字符串解析和构造规则。
4.1. System Query Options
系统查询选项是客户端可以指定的查询字符串参数,用于控制OData服务为URI标识的资源返回的数据的数量和顺序。所有系统查询选项的名称都以“$”字符作为前缀。
OData服务可以支持部分或全部定义的系统查询选项。如果数据服务不支持系统查询选项,它必须拒绝任何包含由[OData:Operations]中的请求处理规则定义的不支持选项的请求。
4.2. Orderby System Query Option ($orderby)
带有$orderby系统查询选项的数据服务URI指定了一个表达式,用于确定使用哪些值对URI的Resource Path部分标识的条目集合进行排序。此查询选项仅在资源路径标识条目集合时才支持。
规范OData规范的$orderby部分概述了该查询选项支持的完整表达式语法。下面的示例表示该表达式语法最常支持的子集。
Examples
https://services.odata.org/OData/OData.svc/Products?$orderby=Rating
- 按Rating属性排序时,以升序返回所有产品条目。
https://services.odata.org/OData/OData.svc/Products?$orderby=Rating asc
- 与上面的例子相同。
https://services.odata.org/OData/OData.svc/Products?$orderby=Rating,Category/Name desc
- 与上面的URI相同,只是product集合随后按照相关Category条目的Name属性进行排序(按降序排列)。
4.3. Top System Query Option ($top)
带有$top系统查询选项的数据服务URI标识由URI的资源路径部分标识的条目集合中的条目子集。这个子集是通过只选择集合的前N个项目形成的,其中N是一个大于等于该查询选项指定的零的整数。如果指定的值小于零,则认为URI格式不正确。
如果数据服务URI包含$top查询选项,但不包含$orderby选项,则数据服务首先需要对集合中的条目进行完全排序。虽然没有强制要求排序语义,但为了确保可重复的结果,数据服务必须始终使用相同的语义来获得跨请求的完整排序。
Examples
https://services.odata.org/OData/OData.svc/Products?$top=5
- 返回的前5个产品条目使用OData服务确定的方案对产品集合进行排序。
https://services.odata.org/OData/OData.svc/Products?$top=5&$orderby=Name desc
- 按Name属性排序时,前5个Product Entries按降序返回。
4.4. Skip System Query Option ($skip)
带有$skip系统查询选项的数据服务URI标识由URI的资源路径部分标识的条目集合中的条目子集。该子集通过在集合中查找N个条目并仅选择剩余的条目(从条目N+1开始)来定义。N是一个大于或等于此查询选项指定的零的整数。如果指定的值小于零,则认为URI格式不正确。
如果数据服务URI包含$skip查询选项,但不包含$orderby选项,则集合中的条目必须首先由数据服务完全排序。虽然没有强制要求排序语义,但为了确保可重复的结果,数据服务必须始终使用相同的语义来获得跨请求的完整排序。
Examples
https://services.odata.org/OData/OData.svc/Categories(1)/Products?$skip=2
- 从第三个产品开始的一组产品条目(与由键值1标识的类别条目相关联)。
https://services.odata.org/OData/OData.svc/Products?$skip=2&$top=2&$orderby=Rating
- 当集合按评级(升序)排序时,所有产品集合中的第三和第四个产品条目。
4.5. Filter System Query Option ($filter)
带有$filter系统查询选项的URI从URI的资源路径部分标识的条目集合中标识条目的子集。该子集是通过只选择满足查询选项指定的谓词表达式的条目来确定的。
$filter操作符中使用的表达式语言支持对属性和文字的引用。文字值可以是用单引号括起来的字符串、数字和布尔值(true或false),也可以是抽象类型系统一节中显示的任何其他文字表示形式。
注意:规范OData规范的$filter部分为该查询选项支持的表达式语言提供了ABNF语法。
表达式语言支持的操作符如下表所示。
算子 | 描述 | 范例 |
---|---|---|
逻辑运算符 | ||
Eq | Equal | /Suppliers?$filter=Address/City eq ‘Redmond’ |
Ne | Not equal | /Suppliers?$filter=Address/City ne ‘London’ |
Gt | Greater than | /Products?$filter=Price gt 20 |
Ge | Greater than or equal | /Products?$filter=Price ge 10 |
Lt | Less than | /Products?$filter=Price lt 20 |
Le | Less than or equal | /Products?$filter=Price le 100 |
And | Logical and | /Products?$filter=Price le 200 and Price gt 3.5 |
Or | Logical or | /Products?$filter=Price le 3.5 or Price gt 200 |
Not | Logical negation | /Products?$filter=not endswith(Description,‘milk’) |
算术运算符 | ||
Add | Addition | /Products?$filter=Price add 5 gt 10 |
Sub | Subtraction | /Products?$filter=Price sub 5 gt 10 |
Mul | Multiplication | /Products?$filter=Price mul 2 gt 2000 |
Div | Division | /Products?$filter=Price div 2 gt 4 |
Mod | Modulo | /Products?$filter=Price mod 2 eq 0 |
分组操作符 | ||
( ) | Precedence grouping | /Products?$filter=(Price sub 5) gt 10 |
除了操作符之外,还定义了一组用于过滤器查询字符串操作符的函数。下表列出了可用的函数。注意:没有定义ISNULL或COALESCE操作符。相反,有一个空字面值可以在比较中使用。
4.6. Expand System Query Option ($expand)
带有$expand系统查询选项的URI表示与URI的资源路径部分标识的条目或条目集合相关的条目必须内联表示(即急切加载)。例如,如果您想标识一个类别及其产品,您可以使用两个uri(并执行两个请求),一个用于/Categories(1),另一个用于/Categories(1)/ products。'$expand’选项允许您使用单个URI识别相关的条目,这样就可以使用单个HTTP请求检索条目图。
$expand查询选项的语法是逗号。
Examples
https://services.odata.org/OData/OData.svc/Categories?$expand=Products
- 标识类别集合以及与每个类别相关联的每个产品。
- 由名为“Categories”的实体集和服务元数据文档中“Category”实体类型上的“Products”导航属性描述。
https://services.odata.org/OData/OData.svc/Categories?$expand=Products/Suppliers
- 标识类别集合以及与每个类别相关联的每个产品。此外,URI还标识与每个产品相关联的供应商。
- 由服务元数据文档中名为“Categories”的实体集、“Categories”实体类型上的“Products”导航属性和“Products”实体类型上的“Suppliers”导航属性描述。
https://services.odata.org/OData/OData.svc/Products?$expand=Category,Suppliers
- 识别产品集以及与每个产品相关联的类别和供应商。
- 由名为“产品”的实体集以及服务元数据文档中“产品”实体类型上的“Categories”和“Products”导航属性描述。
4.7. Format System Query Option ($format)
带有$format系统查询选项的URI指定对请求的响应必须使用查询选项指定的媒体类型。如果$format查询选项出现在请求URI中,它优先于Accept请求报头中指定的值。下表列出了$format查询字符串选项的有效值。
$format Value | Response Media Type |
---|---|
Atom | application/atom+xml |
Xml | application/xml |
Json | application/json |
Any other IANA-defined content type | Any IANA-defined content type |
A service-specific value indicating a format specific to the specific OData service | Any IANA-defined content type |
Examples
https://services.odata.org/OData/OData.svc/Products?$format=atom
- 标识所有使用[OData:Atom]中定义的AtomPub格式表示的产品条目。
https://services.odata.org/OData/OData.svc/Products?$format=json
- 识别使用JSON格式表示的所有产品条目,如[OData:JSON]中定义的那样。
4.8. Select System Query Option ($select)
带有$select System Query选项的数据服务URI与没有$select Query选项的URI标识相同的条目集;但是,$select的值指定来自OData服务的响应应该返回属性的一个子集,如果URI不包含$select查询选项,就会返回这个子集。
版本注意:此查询选项仅在OData 2.0及以上版本中受支持。
$select系统查询选项的值是一个以逗号分隔的选择子句列表。每个选择子句可以是属性名、导航属性名或“*”字符。
Examples
https://services.odata.org/OData/OData.svc/Products?$select=Price,Name
- 在OData服务的响应中,仅为标识的产品集合中的每个产品条目返回Price和Name属性值。
- 如果$select查询选项列出了标识复杂类型的属性,则必须返回在复杂类型上定义的所有属性。
https://services.odata.org/OData/OData.svc/Products?$select=Name,Category
- 在OData服务的响应中,应该只返回每个产品的Name Property值和到相关Category Entry的链接。
- 在OData服务的响应中,应该只返回类别条目的名称,但应该返回产品和供应商导航属性标识的条目的所有属性。
https://services.odata.org/OData/OData.svc/Products?$select=*
- 在OData服务的响应中,为产品实体集中的每个产品条目返回所有属性。
- 注意:星型语法用于引用由URI路径标识的条目或条目集合的所有属性或导航属性的所有属性。换句话说,“*”语法导致包含条目上的所有属性,而不遍历关联。
https://services.odata.org/OData/OData.svc/Categories?\$select=Name,Products&$expand=Products
- 在OData服务的响应中,包含Name属性和包含所有属性的Product Entries;但是,不是包括扩展子句中引用的完全扩展的供应商条目,而是每个产品将包含一个引用相应的供应商条目集合的链接。
注意:规范性OData规范的$select部分为该查询选项支持的表达式语言提供了ABNF语法。
4.9. Inlinecount System Query Option ($inlinecount)
带有 $inlinect系统查询选项的URI指定对请求的响应包括由URI的资源路径部分标识的条目集合中的条目数的计数。必须在应用URI中存在的任何$filter System Query Options之后计算该计数。$inlinecount查询选项的有效值集如下表所示。如果指定的值不是表4中所示的值,则认为URI格式不正确。
版本注意:此查询选项仅在OData 2.0及以上版本中受支持。
$inlinecount value | 说明 |
---|---|
allpages | OData必须包含由URI标识的集合中实体的数量(在应用URI上存在的任何$filter System Query Options之后)。 |
none | OData服务绝对不能在响应中包含计数。这等价于不包含$inlinecount查询字符串参数的URI。 |
Examples
https://services.odata.org/OData/OData.svc/Products?$inlinecount=allpages
- 标识所有产品条目和所有产品的计数。
- 标识花费超过200的前10个产品条目,并包含花费超过200的产品条目总数。
5. Custom Query Options
自定义查询选项为特定于OData服务的信息提供了一个扩展点,这些信息将放置在URI的查询字符串部分中。自定义查询字符串选项定义为任何名称/值对查询字符串参数,其中参数名称不以“$”字符开头。OData服务公开的任何URI都可以包含一个或多个自定义查询选项。
Examples
https://services.odata.org/OData/OData.svc/Products?x=y
- 标识所有产品实体。包括一个自定义查询选项“x”,其含义是服务特定的。
6. Service Operation Parameters
服务操作表示OData服务公开的功能。这些函数可以接受零个或多个基本类型参数。如果服务操作需要输入参数,这些参数将通过附加到URI的查询字符串名称/值对传递,该URI标识服务操作,如寻址服务操作部分所述。对于可空类型参数,可以通过在URI的查询字符串中不包括参数来指定空值。
Examples
https://services.odata.org/OData/OData.svc/GetProductsByRating?rating=5
- 标识“GetProductsByRating”服务操作,并为“rating”输入参数指定值5。
7. URI Equivalence
当确定两个URI是否相等时,每个URI应该使用[RFC3987]和[RFC3986]中指定的规则进行规范化,然后使用HTTP [RFC 2616], Section 3.2.3中指定的等价规则进行比较。