版本1.0

What's RAML ?

RAML: RESTful API Modeling Language即RESTful API建模语言,是对RESTful API的一种简单直接的描述。它是一种让人们易于阅读且能让机器对特定文档可以解析的语言。RAML是基于YAML,符合1.2版本规范。通过RAML定义,因为机器可以解析,所以RAML规范提供了一些机制,可以定义实际的RESTful API,创建client / server源代码,以及为用户生成API文档。

本文中一些关键字 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" 是被描述为 IETF RFC 2119 在 RFCs 中的关键字指示需求级别。

RAML中包含以下内容:

  • Basic Information. How to describe core aspects of the API, such as its name, title, location (or URI), and defaults and how to include supporting documentation for the API.
  • Data Types. Modeling API data through a streamlined type system that encompasses JSON Schema and XML Schema (XSD).
  • Resources. How to specify API resources and nested resources, as well as URI parameters in any URI templates.
  • Methods. How to specify the methods on API resources and their request headers, query parameters, and request bodies.
  • Responses. The specification of API responses, including status codes, media types, response headers, and response bodies.
  • Resource Types and Traits. The optional use of RAML resource types and traits to characterize resources.
  • Security. Specifying an API security scheme in RAML.
  • Annotations. Extending a RAML specification by defining strongly-typed annotations and applying them throughout the specification.
  • Includes, Libraries, Overlays, and Extensions. How an API definition can consist of externalized definition documents, packaging collections of such definitions into libraries, separating and overlaying layers of metadata on a RAML document, and extending an API specification with additional functionality.

版本声明(MUST)

用 "#" 表示文档中行注释的开始,RAML API 定义 MUST 符合 YAML 1.2 的文档,以指示 RAML 版本的 REQUIRED YAML 注释行开头,RAML API 定义文档的第一行 MUST 以文本 #%RAML 开头,后跟一个空格,后跟版本号,在行尾之前没有其他内容。如下所示:

#%RAML 1.0
title: My API

文档根节点

RAML 文档的根节点描述了 API 的基本信息,例如它的标题和版本。 根部分还定义了 RAML 文档中其他地方使用的资产,例如类型和特征。处理器MUST保留节点在文档中的顺序。

#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com
mediaType:  application/json
securitySchemes:oauth_2_0: !include securitySchemes/oauth_2_0.raml
types:Gist:  !include types/gist.ramlGists: !include types/gists.raml
resourceTypes:collection: !include types/collection.raml
traits:
securedBy: [ oauth_2_0 ]
/users:type: collectionget:

下表列举了 RAML 文档根目录的可能节点:

Name Description
title API 的简短纯文本标签。 它的值是一个字符串。
description?

对 API 的实质性、人性化的描述。 它的值是一个字符串,可以使用 markdown 进行格式化。

version? API 的版本,例如“v1”。 它的值是一个字符串。
baseUri? API访问的基础路径。
baseUriParameters? baseUri 中使用的命名参数。
protocols? API支持的访问协议 protocols,如果没有定义此属性值,默认为仅支持baseUri所采用的协议。
mediaType? API request和response bodies(payloads) 的媒体类型 default media types, 如 "application/json".
documentation? API 的其他整体文档。
schemas?(已弃用)

与 RAML 0.8 兼容的等效与“types”节点的别名。 已弃用 - API 定义 SHOULD 使用“types”节点,因为RAML 新版本可能会删除该节点的“schemas”别名。 “types”节点支持 XML 和 JSON 模式。

types? 在 API 中使用的(数据)类型声明。
traits? 在 API 中使用的方法特征 traits 声明.
resourceTypes? 在 API 中使用的资源类型 resource types 声明.
annotationTypes? Declarations of annotation types for use by annotations.
(<annotationName>)?

应用于此 API 的注释。 注释是具有以“(”开头并以“)”结尾的键的映射,其中括号中的文本是注释名称,值是该注释的实例。

securitySchemes? 在API中使用的安全方案 security schemes 声明.
securedBy? 适用于 API 中每个资源和方法的安全方案security schemes.
uses? 导入的外部库以在 API 中使用。
/<relativeUri>?

API 的资源,标识为以斜杠 (/) 开头的相对 URI。 资源节点是以斜杠开头的节点,它位于 API 定义的根节点或资源节点的子节点。 例如,/users 和/{userId}。

“schemas”和“types”节点是互斥和同义的:处理器不允许(MUST NOT)在 API 定义的根级别同时指定两者。 建议使用“types”节点而不是“schemas”,因为schemas别名已被弃用,并且可能在未来的 RAML 版本中被删除。

documentation(OPTIONAL)

文档节点是可选的,包括用作 API 的用户指南和参考文档。 此类文档可以阐明 API 的工作原理或提供技术和业务上下文。

每个文档都是一个映射,它必须(MUST)具有下表中描述的两个键值对:

Name Description
title 文档的标题。 它的值必须(MUST)是一个非空字符串。
content 文档的内容。 它的值必须(MUST)是非空字符串,并且可以使用 markdown 进行格式化。​

下面示例显示了具有两个用户文档的 API 定义。

#%RAML 1.0
title: ZEncoder API
baseUri: https://app.zencoder.com/api
documentation:- title: Homecontent: |Welcome to the _Zencoder API_ Documentation. The _Zencoder API_allows you to connect your application to our encoding serviceand encode videos without going through the web  interface. Youmay also benefit from one of our[integration libraries](https://app.zencoder.com/docs/faq/basics/libraries)for different languages.- title: Legalcontent: !include docs/legal.markdown

baseUri 和 baseUriParameters(OPTIONAL)

baseUri是可选的节点,是API访问的基础路径,baseUri的值必须符合URI 规范 RFC2396 或是一个模板 URI。如果 baseUri 值是模板 URI,则以下保留的基本 URI 参数可用。

URI Parameter Value
version 根节点version节点的值

模板 URI 是指 URI 参数,它是一个变量元素,包含在资源的相对 URI 内的大括号 ({}) 中。

以下示例 RAML API 定义使用模板 URI 作为基本 URI。

#%RAML 1.0
title: Salesforce Chatter REST API
version: v28.0
baseUri: https://na1.salesforce.com/services/data/{version}/chatter

以下示例声明了一个显式的baseUriParameters。

#%RAML 1.0
title: Amazon S3 REST API
version: 1
baseUri: https://{bucketName}.s3.amazonaws.com
baseUriParameters:bucketName:description: The name of the bucket

当baseUri 的值以一个或多个斜杠 (/) 结尾时,使用此 URI 绝对路径时将省略尾部斜杠。 例如,在以下代码段中,资源的绝对路径为 http://api.test.com/common/users/:userId 和 http://api.test.com/common/users/:userId/groups .

baseUri: http://api.test.com/common/
/users:/{userId}:/groups:

在以下更复杂的示例中,在多个位置有连续斜杠,只有 baseUri 中的尾部斜杠被折叠,导致这些资源的绝对路径变成://api.test.com//common/,//api.test.com//common//users//:userId// 和 //api.test.com//common//users//:userId//groups//。

baseUri: //api.test.com//common//
/:/users/:/{userId}/:/groups//:

protocols(OPTIONAL)

protocols 节点是可选的,用来指定API支持的访问协议。如果未明确指定协议节点,则应使用包含在 baseUri 节点中的一个或多个协议; 如果明确指定了协议节点,则此类节点规范应覆盖 baseUri 节点中包含的任何协议。 协议节点必须是一个非空的字符串数组,包含 HTTP 和/或 HTTPS 值,并且不区分大小写。

#%RAML 1.0
title: Salesforce Chatter REST API
version: v28.0
protocols: [ HTTP, HTTPS ]
baseUri: https://na1.salesforce.com/services/data/{version}/chatter

mediaType(OPTIONAL)

mediaType 节点是可选的,用来指定整个API request body和response的默认媒体类型,不需要在每个body定义中指定媒体类型。mediaType 可以配置一个或多个,如下所示:

如下示例 API 接受并返回 JSON 格式正文。 如果此 API 规范的其余部分未明确指定其他媒体类型,则此 API 仅接受并返回 JSON 格式的正文。

#%RAML 1.0
title: New API
mediaType: application/json

如下示例显示了一个用于接受和返回 JSON 或 XML 格式主体的 API 的 RAML 片段。

#%RAML 1.0
title: New API
mediaType: [ application/json, application/xml ]

在API request body或者response下显示定义mediaType节点会重写全文的默认mediaType,如下例所示,资源 /messages 通过显式定义 application/json 节点来覆盖默认媒体类型,因此资源 /messages 仅返回 JSON 格式的正文。

#%RAML 1.0
title: New API
mediaType: [ application/json, application/xml ]
types:Person:Another:
/people:get:responses:200:body: Person[]
/messages:post:body:application/json:type: Another

securedBy 和 securitySchemes(OPTIONAL)

通过这两个节点为API中每个资源的每个方法设置默认安全方案并保护它,securedBy节点的值必须是安全方案名称的数组,securitySchemes节点负责定义一个或多个安全方案。以下示例演示通过OAuth 2.0或 OAuth 1.0安全方案访问API。

#%RAML 1.0
title: Dropbox API
version: 1
baseUri: https://api.dropbox.com/{version}
securedBy: [ oauth_2_0, oauth_1_0 ]
securitySchemes:oauth_2_0: !include securitySchemes/oauth_2_0.ramloauth_1_0: !include securitySchemes/oauth_1_0.raml

RAML Data Types

RAML 1.0引入了数据类型概念,通过 types 节点来定义数据类型,数据类型添加了用于根据类型声明验证数据的规则。数据类型可以描述baseUri或resource Uri的参数、查询参数、request header或response header、request body或response body。数据类型可以是内置的或自定义的,内置类型可以在API需要数据的任何地方使用,自定义类型可以通过扩展内置类型来定义,也可以像内置类型一样命名和使用。但是扩展类型不能(MUST NOT)创建任何循环依赖,可以内联扩展类型。

下面示例自定义了一个User类型,包含firstname、lastname 和 age 属性,属性声明为内置类型string和number,后面User类型用来描述payload的类型。

#%RAML 1.0
title: API with Types
types:User:type: objectproperties:firstname: stringlastname:  stringage:       number
/users/{id}:get:responses:200:body:application/json:type: User

RAML 类型声明类似于 JSON 模式定义。 事实上,RAML 类型可以用来代替 JSON 和 XML 模式,或者与它们共存。 然而,RAML 类型语法被设计为比 JSON 和 XML 模式更简单、更简洁,同时保留了它们的灵活性和表现力。 以下代码段显示了一些类型声明的示例:

#%RAML 1.0
title: My API with Types
mediaType: application/json
types:Org:type: objectproperties:onCall: AlertableAdminHead: ManagerPerson:type: objectproperties:firstname: stringlastname:  stringtitle?:    stringPhone:type: stringpattern: "[0-9|-]+"Manager:type: Personproperties:reports: Person[]phone:  PhoneAdmin:type: Personproperties:clearanceLevel:enum: [ low, high ]AlertableAdmin:type: Adminproperties:phone: PhoneAlertable: Manager | AlertableAdmin
/orgs/{orgId}:get:responses:200:body:application/json:type: Org

RAML 类型特征:

  • RAML类型类似于 Java 类,借鉴了面向对象语言、Json Schema和XML Schema (XSD)。
  • 你可以定义从其他类型继承的类型。并允许多重继承。
  • RAML类型可以被分为四种:external, object, array, scalar(标量).
  • RAML类型可以定义两种类型的成员:属性和构面。 两者都是继承的。属性是常规的、面向对象的属性。构面是特殊的配置。 你可以根据构面值的特征定制化类型。 示例:最小长度、最大长度。
  • 只有对象类型可以声明属性。 但所有类型都可以声明构面。
  • 要定制化标量类型,你需要实现构面,为已定义的构面赋予具体值。
  • 要定制化对象类型,你需要定义属性。

types可以用在RAML中的很多个地方:

  • Body ( JSON )
  • Body ( XML )
  • Body ( Web Form )
  • Headers
  • Query Parameters
  • URI Parameters

RAML类型定义

RAML类型应在 API 需要数据的地方内联声明,在 API 根types节点中,或在包含的库中。 要声明类型,您必须使用映射,其中键表示类型名称,值是类型声明。

types:Person: # key name# value is a type declaration

类型声明

类型声明引用另一种类型,或者通过添加功能方面(例如属性)或非功能方面(例如描述)来包装或扩展另一种类型,或者是使用其他类型的类型表达式。 以下是所有类型声明都可以具有的方面; 某些类型声明可能有其他方面:

Facet Description
default? 默认值
schema? (已弃用) 与 RAML 0.8 兼容等效“type”的别名。 已弃用 - API 定义应该使用“type”,因为“schema”可能会在未来的 RAML 版本中被删除。 “type”支持 XML 和 JSON 模式。
type? 当前类型扩展或引用的类型。type节点的值必须是:a) 自定义类型名称;b) 内置RAML数据类型(对象、数组、标量)的名称;c) 内联类型声明;
example? 示例,如果examples节点已经定义,那么当前example节点不可用,二者不可共存
examples? 示例,如果example节点已经定义,那么当前examples节点不可用,二者不可共存
displayName? 类型的替代的、人性化的名称
description? 对该类型的描述。 值是字符串,可以使用 markdown 进行格式化。
(<annotationName>)? 要应用于此 API 的注释。 注释是具有以“(”开头并以“)”结尾的键的映射,其中括号中的文本是注释名称,值是该注释的实例。
facets?

由任何扩展子类型继承和应用的附加用户定义限制的映射。

xml? 配置此类型实例的 XML 序列化的能力。 XML serialization of this type instance.
enum? 此类型的所有可能值的枚举。

注意:“schema”和“type”是互斥和同义的:处理器不允许在同一类型声明中显式或隐式同时指定两者。 因此,以下示例无效:

types:Person:schema: # invalid as mutually exclusive with `type`type: # invalid as mutually exclusive with `schema`/resource:get:responses:200:body:application/json: # start type declarationschema: # invalid as mutually exclusive with `type`type: # invalid as mutually exclusive with `schema`

内置类型

  • any
  • object
  • array
  • union via type expression
  • scalar types: number, boolean, string, date-only, time-only, datetime-only, datetime, file, integer, or nil

除了上面内置类型之外,RAML类型还允许JSON或XML的定义。

any类型

任何类型,无论是内置的还是用户定义的,在其继承树的根部都有 any 类型。 any 类型是一种不施加任何限制的类型,即任何数据实例都对其有效。但是any类型没有任何额外的facets。

Object类型

所有object类型都可以在其类型声明中使用以下方面:

Facet Description
properties? 对象的属性
minProperties? 此类型实例允许的最小属性数。
maxProperties? 此类型实例允许的最大属性数。
additionalProperties? 一个布尔值,表示对象实例是否可以包含其他属性。Default: true
discriminator?

在运行时决定单个对象的具体类型,例如payloads中由于联合或继承包含不明确的类型。该值必须与当前类型的声明属性之一的名称匹配。 不支持的做法是内联类型声明和使用具有非标量属性的鉴别器。

discriminatorValue? 标识声明类型。 需要在类型声明中包含discriminator。 有效值是可能标识单个对象类型的实际值,并且在类型的层次结构中是唯一的。 不支持内联类型声明。Default: The name of the type

示例如下:

#%RAML 1.0
title: My API With Types
types:Person:type: objectproperties:name:required: truetype: string

properties声明(OPTIONAL)

properties是可选的,RAML规范将属性方面的值定义为属性声明。属性声明必须是键和值的映射。 键是用于声明类型实例的有效属性名称。 值必须是类型名称或内联类型声明。属性声明可以指定属性是必需的还是可选的。 或者,键名中的尾随问号 (?) 可用于指示属性是可选的。

Facet Description
required? 指定属性是否是必须的。Default: true.

以下示例声明一个对象有两个属性:

types:Person:properties:name:required: truetype: stringage:required: falsetype: number

上面的实例可以简写成:

types:Person:properties:name: string # equivalent to -># name:#  type: stringage?: number # optional property; equivalent to -># age:#  type: number#  required: false

如果在类型声明中明确指定了required,那么属性名称中的任何问号必须被视为属性名称的一部分,而不能作为该属性是否可选的指示符。例如profile有一个属性 preference? 包好了问号,那么有两种声明方式:a) 属性名称后追加?表示可选;b) 在属性声明中添加required来标识是否必须。示例如下:

types:profile:properties:preference??:
types:profile:properties:preference?:required: false

注意:当对象类型不包含“properties”节点时,假定对象不受约束,因此能够包含任何类型的任何属性。

Additional Properties

默认情况下,对象的任何实例都可以具有超出其数据类型属性方面指定的其他属性。 假设以下代码是上一节中描述的数据类型 Person 的一个实例。属性note没有在 Person 数据类型中声明,但它是有效的,因为默认情况下所有附加属性都是有效的。

Person:name: "John"age: 35note: "US" # valid additional property `note`

要限制属性的添加,可以将additionalProperties的值设置为 false,或者可以通过正则表达式指定匹配键集并限制其值。 后者称为“模式属性”。 模式由成对的开始和结束 / 字符描述,如下所示:

#%RAML 1.0
title: My API With Types
types:Person:properties:name:required: truetype: stringage:required: falsetype: number/^note\d+$/: # restrict any properties whose keys start with "note"# followed by a string of one or more digitstype: string

此模式属性限制属性键以“note”开头后跟一个或多个数字,值是字符串类型的任何其他属性。

Person:name: "John"age: 35note1: "US" # validnote2: 123 # not valid as it is not a stringnote: 123 # valid as it does not match the pattern

要强制所有附加属性为字符串类型,无论其属性名如何,请使用 // :

#%RAML 1.0
title: My API With Types
types:Person:properties:name:required: truetype: stringage:required: falsetype: number//: # force all additional properties to be a stringtype: string

如果模式属性正则表达式也匹配显式声明的属性,则显式声明的属性定义优先。 如果两个或多个模式属性正则表达式匹配数据类型实例中的属性名称,则以第一个为准。

此外,如果指定了additionalProperties为false(显式或通过继承),则不允许通过正则表达式显式设置模式属性。 如果指定了 additionalProperties 为true(或省略),则允许模式属性并进一步限制该类型中允许的附加属性。

object类型定制化

你可以声明继承自其他对象类型的对象类型(通过type指定继承的父类型)。 子类型继承其父类型的所有属性。 在下面的示例中,类型 Employee 继承了其父类型 Person 的所有属性。

#%RAML 1.0
title: My API With Types
types:Person:type: objectproperties:name:type: stringEmployee:type: Personproperties:id:type: string

子类型可以覆盖其父类型的属性,但有以下限制:

1) 父类型中的必需属性不能更改为子类型中的可选属性;

2) 父类型中已定义属性的类型声明,只能在子类型中更改为更窄的类型(父类型的特化)。

array类型

数组类型必须通过数组限定符 [] 结尾来声明。 如果你正在定义顶级数组类型,例如下面示例中的Emails,你可以在前面描述的之外声明以下方面,以进一步限制数组类型的行为。

Facet Description
uniqueItems? Boolean值,指示数组中的项目是否必须是唯一的。
items? 指示数组中所有项的继承类型。 可以是对现有类型或内联类型声明的引用。
minItems? 数组项目最小数。 值必须等于或大于 0。Default: 0.
maxItems? 数组项目最大数。 值必须等于或大于 0。Default: 2147483647.

以下两个示例的写法都是正确的:

types:Email:type: objectproperties:subject: stringbody: stringEmails:type: Email[]minItems: 1uniqueItems: trueexample: # example that contains array- # start item 1subject: My Email 1body: This is the text for email 1.- # start item 2subject: My Email 2body: This is the text for email 2.  
types:Email:type: objectproperties:name:type: stringEmails:type: arrayitems: EmailminItems: 1uniqueItems: true

scalar类型

RAML 定义了一组内置的标量类型,每个类型都有一组预定义的限制。

String

Facet Description
pattern? 此字符串必须匹配的正则表达式。
minLength? 字符串最小长度,值必选大于等于0. Default: 0
maxLength? 字符串最大长度,值必选大于等于0. Default: 2147483647
types:EmailAddress:type: stringpattern: ^.+@.+\..+$minLength: 3maxLength: 320

Number

Facet Description
minimum? 最小值
maximum? 最大值
format? 值的格式,值必须是其中之一: int, int8, int16, int32, int64, long, float, double.
multipleOf? 如果将实例除以此关键字的值的结果是整数,则数字实例对“multipleOf”有效。
types:Weight:type: numberminimum: -1.1maximum: 20.9format: floatmultipleOf: 1.1

Integer

1的正数或负数,继承自number类型

types:Age:type: integerminimum: -3maximum: 5format: int8

Boolean

没有任何附件方面描述

types:IsMarried:type: boolean

Date

必须支持以下日期类型的表示:

Type Description
date-only RFC3339 的“完整日期”表示法,即 yyyy-mm-dd。 不支持时间或时区偏移表示法。
time-only RFC3339 的“部分时间”表示法,即 hh:mm:ss[.ff...]。 不支持日期或时区偏移表示法。
datetime-only

将仅date-only和time-only通过“T”分隔符组合在一起,即 yyyy-mm-ddThh:mm:ss[.ff...]。 不支持时区偏移。

datetime

以下格式之一的时间戳:如果格式被省略或设置为 rfc3339,则使用 RFC3339 的“date-time”表示法; 如果格式设置为 rfc2616,则使用 RFC2616 中定义的格式。

仅当类型等于 datetime 时,附加方面 format 必须可用:

Facet Description
format? datetime 类型的值的格式。 该值必须是 rfc3339 或 rfc2616。 任何其他值均无效。
types:birthday:type: date-only # no implications about time or offsetexample: 2015-05-23lunchtime:type: time-only # no implications about date or offsetexample: 12:30:00fireworks:type: datetime-only # no implications about offsetexample: 2015-07-04T21:00:00created:type: datetimeexample: 2016-02-28T16:41:41.090Zformat: rfc3339 # the default, so no need to specifyIf-Modified-Since:type: datetimeexample: Sun, 28 Feb 2016 16:41:41 GMTformat: rfc2616 # this time it's required, otherwise, the example format is invalid

File

文件类型可以限制内容通过表单发送。 当在 web 表单的上下文中使用此类型时,它应该表示为 JSON 格式的有效文件上传。 文件内容应该是 base64 编码的字符串。

Facet Description
fileTypes? 文件允许的content-type列表。 文件类型 */* 必须是有效值。
minLength? 指定参数值的最小字节数。 该值必须等于或大于 0。Default: 0
maxLength? 指定参数值的最大字节数。 该值必须等于或大于 0。Default: 2147483647
types:userPicture:type: filefileTypes: ['image/jpeg', 'image/png']maxLength: 307200customFile:type: filefileTypes: ['*/*'] # any file type allowedmaxLength: 1048576

Nil类型

将属性的类型声明为 nil 表示类型实例中缺少值。 在需要 nil 类型的值(与仅类型声明相比)的 RAML 上下文中,通常使用 YAML 的null,例如当类型为 nil | number 时, 可以使用 enum: [ 1, 2, ~ ] 或更明确的 enum: [ 1, 2, !!null "" ]; 当然,在非内联表示法中,您可以完全省略该值。

nil 值与可选的属性不同。 例如,你可以定义一个comment属性是可选的并接受 nil 值,通过语法 comment?: string? 或 comment?: nil | string定义.

types:NilValue:type: objectproperties:name:comment: nil | string # equivalent to -># comment: string?example:name: Fredcomment: # Providing a value or not providing a value here is allowed.

Union联合类型

联合类型可以用于允许数据实例由几种类型中的任何一种来描述。 联合类型必须通过一个类型表达式来声明,该类型表达式组合了由管道 (|) 符号分隔的 2 个或多个类型;

types:CatOrDog:type: Cat | Dog # elements: Cat or DogCat:type: objectproperties:name: stringcolor: stringDog:type: objectproperties:name: stringfangs: string

想象一种更复杂的情况,如下校验 HomeAnimal类型, 处理器必须测试六种可能的组合: [HasHome, Dog ][HasHome, Cat ][HasHome, Parrot][IsOnFarm, Dog ][IsOnFarm, Cat ], and [IsOnFarm, Parrot].

types:HomeAnimal: [ HasHome | IsOnFarm ,  Dog | Cat | Parrot ]

如果联合类型指定了enum,则该枚举的每个值都必须满足与至少一个类型的限制。 这是一个例子:

type: number | boolean
enum: [1, true, 2]

下面的示例是无效的写法,因为 hello 是string类型,既不是number也不是boolean类型:

type: number | boolean
enum: [1, true, 2, "hello"]

联合类型可以使用由其任何成员类型定义的属性,只要联合中的所有成员类型都接受这些属性,例如:

types:Foo: numberBar: integerFooBar:type: Foo | Barminimum: 1 # valid because both "Foo" (number) and "Bar" (integer) all accept "minimum"
types:Foo: numberBar: integerQux: stringFooBarQux:type: Foo | Bar | Quxminimum: 1 # invalid because "Qux" (string) does not accept the "minimum" facet
types:Foo: numberBar: integerQux:type: stringfacets:minimum: numberFooBarQux:type: Foo | Bar | Quxminimum: 1 # valid because "Qux" (string) has a user-defined facet "minimum"

XML and JSON Schemas

RAML 允许使用 XML 和 JSON 模式来描述 API request或response body,方法是将模式集成到其数据类型系统中。

以下示例展示了如何将外部 JSON 包含到根级别类型定义和body声明中。

types:Person: !include person.json
/people/{personId}:get:responses:200:body:application/json:type: !include person.json

RAML 处理器不允许定义 XML 或 JSON 模式的类型参与类型继承或定制,或参与任何类型表达式。 因此,您不得定义这些类型的子类型来声明新属性、添加限制、设置构面或声明构面。 但是,您可以创建简单的类型包装器来添加注释、示例、显示名称或描述。

下面示例是有效的声明:

types:Person:type: !include person.jsondescription: this is a schema describing a person

下面示例是无效的声明,因为类型继承了json特征,还添加了其他属性:

types:Person:type: !include person.jsonproperties: # invalidsingle: boolean

另一个无效情况显示在以下将 Person 类型用作属性类型的示例中:

types:Person:type: !include person.jsondescription: this is a schema describing a personBoard:properties:members: Person[] # invalid use of type expression '[]' and as a property type

您可以引用一个定义在schema中的元素。 RAML 通过使用 URL 片段来支持这一点,如下例所示:

type: !include elements.xsd#Foo

用户自定义构面facet

用户定义的 facet 是在类型声明中使用可选的 facets 声明的。facets 的值必须是一个映射。 键命名用户定义的facet。 相应的值定义了各个facet可以采用的具体值的类型。

#%RAML 1.0
title: API with Types
types:CustomDate:type: date-onlyfacets:onlyFutureDates?: boolean # optional  in `PossibleMeetingDate`noHolidays: boolean # required in `PossibleMeetingDate`PossibleMeetingDate:type: CustomDatenoHolidays: true

默认类型

If, and only if, 当且仅当类型声明包含对该类型唯一的构面时,默认就是此类型。如下properties是object类型独有的构面,所以及时Person需要制定type,默认类型也是object。

types:Person:properties:

如果类型声明里的构面不是某个类型独有的,那么默认是string类型。如下name不是某个类型唯一的,所以默认是string类型。

types:Person:properties:name: # no type or schema necessary since the default type is `string`

body节点的默认类型是any类型,不包含propertiestype, or schema,如下所示:

body:application/json:# default type is `any`
body:# default type is `any`

当然了,每个规则都是可以重写的,通过显示定义type,如下所示:

types:Person:properties:name:type: number

类型表达式

类型表达式提供了一种强大的引用甚至定义类型的方法。 类型表达式可以在任何需要类型的地方使用。 最简单的类型表达式是类型的名称。 使用类型表达式,您可以设计类型联合、数组、映射和其他东西。

Expression Description
Person 最简单的类型表达式,一个单独的类型
Person[] Person对象数组
string[] string标量数组
string[][] 字符串标量的二维数组
string | Person 由string和Person组成的联合类型
(string | Person)[] 联合类型数组,等价于string[] 或 Person[]

类型表达式可以用于任何需要类型的地方:

#%RAML 1.0
title: My API With Typestypes:Phone:type: objectproperties:manufacturer:type: stringnumberOfSIMCards:type: numberNotebook:type: objectproperties:manufacturer:type: stringnumberOfUSBPorts:type: numberPerson:type: objectproperties:devices: ( Phone | Notebook )[]reports: Person[]

您甚至可以从类型表达式“扩展”出其他类型。 例如:

#%RAML 1.0
title: My API With Types
types:Phone:type: objectproperties:manufacturer:type: stringnumberOfSIMCards:type: numberNotebook:type: objectproperties:manufacturer:type: stringnumberOfUSBPorts:type: numberDevices:type:  ( Phone | Notebook )[]

类型表达式语法

类型表达式由内置或自定义类型的名称和某些符号组成,如下所示:

Expression Components Description Examples
type name 一个单独的类型,可以是自定义类型,也可以是内置类型 number: 内置类型
Person: 自定义类型
(type expression) 括号消除了运算符应用的表达式的歧义。 Person | Animal[]
( Person | Animal )[]
(type expression)[] 类型表达式数组 string[]: string类型数组
Person[][]: Person二维数组
(type expression 1) | (type expression 2) | 联合运算符可以在多个表达式之间组合 string | number: string或number
X | Y | Z: X 或 Y 或 Z
(Manager | Admin)[]: Manager[] 或 Admin[]
Manager[] | Admin[]: 和上面的等价

类型多重继承

RAML 类型支持多重继承。 这是通过传递一系列类型来实现的,如下Teacher继承自Employee,又继承自Person:

types:Person:type: objectproperties:name: stringEmployee:type: objectproperties:employeeNr: integerTeacher:type: [ Person, Employee ]

只有当子类型在继承其父类型的所有限制后仍然是有效的类型声明时,才允许多重继承。 不允许从不同类型的原始类型继承,例如 [number, string]。还比如一个类型设置了最小值4,另一个类型设置了最大值2,互相冲突,也是无效的,如下所示:

types:Number1:type: numberminimum: 4Number2:type: numbermaximum: 2Number3: [ Number1, Number2] # invalid, maximum value cannot be less than minimum value

内联类型声明

除了在类型表达式中,您可以在可以引用类型的任何地方声明内联/匿名类型,如下通过type为firstname、lastname、age声明类型:

#%RAML 1.0
title: My API With Types
/users/{id}:get:responses:200:body:application/json:type: objectproperties:firstname:type: stringlastname:type: stringage:type: number

examples(highly RECOMMENDED)

Single Example

有两种方式来表示example值:作为特定类型实例的显式描述,或作为包含附加 facet 的映射。

方式一:显式描述特定类型

title: Attention needed
body: You have been added to group 274

方式二:通过包含附加facet的映射

作为一个map,可以有以下附件的facet:

Facet Description
displayName? example name,如果example是examples节点的一部分,则默认值为为此示例定义的唯一标识符。
description? 对example的描述
(<annotationName>)? 要应用于此 API 的注释。 注释必须是具有以“(”开头并以“)”结尾的键的映射,其中括号中的文本是注释名称,值是该注释的实例。
value example value,实际示例
strict? boolean类型,是否验证示例,一般设置为 false 以避免验证。
(pii): true
strict: false
value:title: Attention neededbody: You have been added to group 274

Multiple Examples

它的值必须是键值对的映射,其中每个键代表一个示例的唯一标识符,值是单个示例。

message: # {key} - unique id# example declarationtitle: Attention neededbody: You have been added to group 274
record: # {key} - unique id# example declarationname: log itemcomment: permission check

在RAML的不同API如何定义示例:

#%RAML 1.0
title: API with Examplestypes:User:type: objectproperties:name: stringlastname: stringexample:name: Boblastname: MarleyOrg:type: objectproperties:name: stringaddress?: stringvalue?: string
/organizations:post:headers:UserID:description: the identifier for the user who posts a new organizationtype: stringexample: SWED-123 # single scalar examplebody:application/json:type: Orgexample: # single request body examplevalue: # needs to be declared since instance contains a 'value' propertyname: Doe Enterprisevalue: Silver
/organizations/{orgId}:get:description: Returns an organization entity.responses:201:body:application/json:type: Orgexamples:acme:name: AcmesoftwareCorp:value: # validate against the available facets for the map value of an examplename: Software Corpaddress: 35 Central Streetvalue: Gold # validate against an instance of the `value` property

resources(MUST)

resource由其相对 URI 标识,该 URI 必须(MUST)以斜杠 (/) 开头。 以斜杠开头的每个节点,可以位于 API 根节点或者是资源节点的子节点。定义在根节点的resource称为顶级资源。 根节点的键是资源相对于 baseUri 的 URI。 定义在一个资源子节点的资源称为嵌套资源。

此示例显示了一个 API 定义,其中包含一个顶级资源 /gists 和一个嵌套资源 /public。

#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com
/gists:displayName: Gists/public:displayName: Public Gists

那么以上资源的绝对路径格式如下:

   "https://api.github.com"               <--- baseUri+"/gists"                     <--- gists resource relative URI+"/public"                    <--- public gists resource relative URI=
"https://api.github.com/gists/public"     <--- public gists absolute URI

嵌套资源本身可以具有子(嵌套)资源,从而创建多重嵌套资源。如下所示,/user是一个没有子资源的顶级资源,/users 是一个有子资源 /{userId}的顶级资源,/{userId} 资源下面又有三个子资源:

#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com
/user:
/users:/{userId}:uriParameters:userId:type: integer/followers:/following:/keys:/{keyId}:uriParameters:keyId:type: integer

那么完整的API URI绝对路径如下所示:

https://api.github.com/user
https://api.github.com/users
https://api.github.com/users/{userId}
https://api.github.com/users/{userId}/followers
https://api.github.com/users/{userId}/following
https://api.github.com/users/{userId}/keys
https://api.github.com/users/{userId}/keys/{keyId}

RAML 处理器不允许计算的绝对路径之一与另一个相同;绝对路径的比较是在不考虑任何 URI 参数的可能值的情况下进行的。如下示例绝对路径是重复的,是禁止的:

/users:/foo:
/users/foo:

但是以下示例是允许的:

/users/{userId}:
/users/{username}:
/users/me:

Resource Property

资源节点的值必须是包含下表中描述的键值对的映射。

Name Description
displayName? 资源名称。 如果没有定义 displayName,默认资源名称的键。
description? 对资源的描述
(<annotationName>)?  要应用于此 API 的注释。 注释必须是具有以“(”开头并以“)”结尾的键的映射,其中括号中的文本是注释名称,值是该注释的实例。
get?
patch?
put?
post?
delete?
options?
head?
API请求方法类型method.
is? 此资源的所有方法的特征列表。 个别方法可以覆盖此声明。
type? 此资源继承的资源类型。
securedBy? 适用于此资源的所有方法的安全方案。
uriParameters? 有关此资源的任何 URI 参数的详细信息。
/<relativeUri>? 嵌套资源是名称以斜杠 (/) 开头的任何节点。 因此,该资源应被视为相对 URI。

Template URIs and URI Parameters

Template URIs包含URI Parameters,如下 /{jobId}:

#%RAML 1.0
title: ZEncoder API
version: v2
baseUri: https://app.zencoder.com/api/{version}
/jobs: # its fully-resolved URI is https://app.zencoder.com/api/{version}/jobsdescription: A collection of jobs/{jobId}: # its fully-resolved URI is https://app.zencoder.com/api/{version}/jobs/{jobId}description: A specific job, a member of the jobs collection

uriParameters 节点的值是一个映射,尤其是属性声明,就像类型声明一样。 声明对象中的每个属性都是一个 URI 参数声明。 每个属性名称对应于模板 URI 中的一个参数名称。 每个属性值都将 URI 参数类型指定为类型名称或内联类型声明。

uriParameters 声明中的每个属性都必须与资源的相对 URI 中的 URI 参数的名称完全对应。 相对 URI 中的所有 URI 参数不需要在 uriParameters 节点中显式指定,但那些未指定的必须被视为字符串类型的 URI 参数并且是必需的。

#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com
/user:description: The currently authenticated User
/users:description: All users/{userId}:description: A specific useruriParameters:userId:description: The id of the usertype: integer

如果 URI 参数声明指定了非标量类型的数组、对象或联合,则处理器必须默认将URI 参数实例的值当成JSON 类型。在此示例中,URI 参数 userIds 是一个 id 数组。 假设数组包含 [blue,green],它在网络上可能显示为 /users/%5B%22blue%22,%22green%22%5D/。

#%RAML 1.0
title: Serialization API/users:description: All users/{userIds}:description: A specific useruriParameters:userIds:description: A list of userIdstype: arrayitems:type: stringminLength: 1uniqueItems: true

Methods

RESTful API 方法是对资源执行的操作。 资源的 OPTIONAL 属性 get、patch、put、post、delete、head 和 options 定义了它的方法。 这些属性对应于 HTTP 版本 1.1 规范 RFC2616 及其扩展 RFC5789 中定义的 HTTP 方法。 这些方法属性的值必须是具有以下键值对的映射:

Name Description
displayName? 方法名字,如果没有定义,则默认方法键为名字。
description? 对方法的描述
(<annotationName>)? 要应用于此 API 的注释。 注释是具有以“(”开头并以“)”结尾的键的映射,其中括号中的文本是注释名称,值是该注释的实例。
queryParameters? 此方法所需的查询参数的详细信息。 与 queryString 互斥。
headers? 有关此方法所需的请求头headers的详细信息。
queryString? 方法所需的查询字符串,与 queryParameters 互斥。
responses? 对请求的预期响应的信息。
body? 该方法的request body
protocols? 允许访问该方法的协议
is? 此方法的特征列表。
securedBy? 此方法的安全方案

Headers(OPTIONAL)

headers的值必须是一个映射,以下示例演示一个post method的HTTP header名为Zencoder-Api-Key:

#%RAML 1.0
title: ZEncoder API
version: v2
baseUri: https://app.zencoder.com/api/{version}
/jobs:post:description: Create a jobheaders:Zencoder-Api-Key:description: The API key needed to create a new job

如果标头声明为标头的值指定了数组类型,处理器必须允许在请求或响应中出现该标头的多个实例。 在这种情况下,数组元素的类型必须作为头实例值的类型应用。

#%RAML 1.0
title: Example with headers
traits:chargeable:headers:X-Dept:type: arraydescription: |A department code to be charged.Multiple of such headers are allowed.items:pattern: ^\d+\-\w+$example: 230-OCTOtraceable:headers:X-Tracker:description: A code to track API calls end to endpattern: ^\w{16}$example: abcdefghijklmnop
/users:get:is: [ chargeable, traceable ]description: |The HTTP interaction will look likeGET /users HTTP/1.1X-Dept: 18-FINANCEX-Dept: 200-MISCX-Tracker: gfr456d03ygh38s2headers:X-Dept:example: [ 18-FINANCE, 200-MISC ]X-Tracker:example: gfr456d03ygh38s2

Query Strings和Query Parameters(OPTIONAL)

API 方法可能支持或需要在调用该方法的 URL 中的查询字符串。 URL 中的查询字符串用于 URL 中问号分隔符 (?) 和任何片段 (#) 分隔符之前的部分。 查询字符串可以由 queryString 节点或 queryParameters 节点指定。 queryString 和 queryParameters 节点互斥:处理器不得允许在同一资源的同一方法上显式或隐式同时指定两者。

Query String作为一个整体

queryString 节点可用于将查询字符串指定为一个整体,而不是名称-值对。 queryString 值必须是数据类型的名称或内联数据类型声明,包括数据类型表达式。

如果该类型派生自标量类型,则查询字符串作为一个整体必须由该类型描述。

如果类型派生自对象类型,处理器必须将查询字符串视为此对象类型实例的 URL 编码序列化。 查询字符串的格式必须为“parameter1=value1&parameter2=value2&...”,其中“parameter1”、“parameter2”等对应于对象类型中的属性。 同样,“value1”、“value2”等对应于对象类型中的值规范。 如果对象类型中的属性值是数组类型,处理器必须允许在查询字符串中出现该查询参数的多个实例。 在这种情况下,数组元素的类型必须应用为该查询参数实例值的类型。

#%RAML 1.0
title: Illustrate query parameter variations
types:lat-long: # lat & long required; mutually exclusive with locationproperties:lat: numberlong: numberloc: # location required; mutually exclusive with lat & longproperties:location:paging: # each is optional, not exclusive with anythingproperties:start?: numberpage-size?: number
/locations:get:queryString:type: [paging,  lat-long | loc ]examples:first:value:start: 2lat: 12long: 13second:value:start: 2page-size: 20location: 1,2third:  # not validvalue:lat: 12location: 2strict: false # because it's not valid

Query String中的Query Parameters

queryParameters 节点指定组成查询字符串的查询参数集。

以下示例演示一个get 方法使用 HTTP queryParameters。 使用示例值向 https://api.github.com/v3/users?page=1&per_page=50 发送请求。

#%RAML 1.0
title: GitHub API
version: v3
baseUri: https://api.github.com/{version}
/users:get:description: Get a list of usersqueryParameters:page:description: Specify the page that you want to retrievetype:        integerrequired:    trueexample:     1per_page:description: Specify the amount of items that will be retrieved per pagetype:        integerminimum:     10maximum:     200default:     30example:     50

body(OPTIONAL)

可以使用 body 节点指定方法的 HTTP request body。 例如POST 或 PUT方法,请求主体通常会包含要创建的资源的详细信息。

参考文献

官方网站:http://raml.org

规范文档:raml-spec/raml-10.md at master · raml-org/raml-spec · GitHub

raml-spec/raml-10.md at master · raml-org/raml-spec · GitHub

设计器:GitHub - mulesoft/api-designer: A web editor for creating and sharing RAML API specifications

JS解析器:GitHub - raml-org/raml-js-parser: (deprecated) A RAML parser based on PyYAML written in CoffeScript and available for use as NodeJs module or in-browser., 生成浏览器可访问的API文档

Java解析器:GitHub - raml-org/raml-java-parser: (deprecated) A RAML parser based on SnakeYAML written in Java, 基于该解析器我们可以开发出生成API文档、API调用客户端代码以及将API定义导入到服务中心的功能。

RAML规范1.0(译文)相关推荐

  1. UASP规范1.0中译本

    故纸堆里翻出来的两年前开始做USB3.0时翻译的UASP规范1.0版本.虽非原创,翻译辛苦,转载请注明出处! 译者:Cory Xie<cory.xie@gmail.com> USB大容量存 ...

  2. LoRaWAN 规范 1.0(2~4章)

    目录(?)[-] LoRaWAN 规范 10 24章 声明 LoRaWAN 简介 1 LoRaWAN Classes 22 规范 物理层消息格式 1 上行链路消息 2 下行链路消息 3 接收窗口 31 ...

  3. Vue开发规范1.0

    2019独角兽企业重金招聘Python工程师标准>>> VUE开发规范-V1.0 前提条件 开发环境:Node 开发工具:推荐 WebStorm 同步工具:Git 推荐开发插件 es ...

  4. 服务器虚拟化专用ovf模板,科学网—开放虚拟化格式规范2.0.0——OVF package - 唐宏伟的博文...

    开放虚拟化格式规范2.0.0--OVF package 学习笔记 开放虚拟化格式规范(Open Virtualization Format Specification)是由DMTF制定的关于虚拟化技术 ...

  5. CDMA 1X WAP2.0业务网 设备实施规范 (V1.0)

    CDMA 1X WAP2.0业务网 设备实施规范 (V1.0) 前 言: 近10年以来,移动通信(包括数据和语音)和Internet几乎成为了在全世界范围内发展最快,最具活力的两项技术.而Intern ...

  6. 解读 | CSA 软件定义边界(SDP)标准规范 2.0 VS 1.0

    关注微信公众号,回复关键词"SDP标准" 即可阅读下载白皮书 2013年,国际云安全联盟CSA率先提出基于零信任理念的新一代网络安全模型-软件定义边界SDP,并于2014年发布了S ...

  7. 【社区治理】币车社区规范V1.0版本

    币车社区不断发展壮大,为了保障社区成员的体验,维护币车社区良好秩序,现公布社区规范如下: 2018年8月29日公布币车社区规范V1.0版本: 一.行为和内容规范 1.禁止发布敏感和恶意内容 1.1 禁 ...

  8. Java编码规范V1.0

     Java编码规范V1.0 1 代码总体原则 1. 清晰第一 清晰性是易于维护.易于重构的程序必需具备的特征.代码首先 是给人读的,其次才给机器用来执行. 目前软件维护期成本占整个生命周期成本的 40 ...

  9. 个人工作室的网站开发规范V1.0

    一,概述 不论是最古老的HTML,还是最近流行的AJAX,网站开发始终是一个综合了多种最新技术的实验场.作为个人工作室,成员屈指可数,多为手工作坊,往往一个人要担任多个角色,既是前台美工,又是后台程序 ...

最新文章

  1. 性能提升19倍,DGL重大更新支持亿级规模图神经网络训练
  2. Zynq器件的时钟系统
  3. 新东方王强老师的感悟
  4. CSS中清除浮动的两种方式
  5. web项目没有run on server时..
  6. Android之View绘制流程开胃菜---setContentView(...)详细分析
  7. php中学院与专业的级联,SQLite中使用CTE巧解多级分类的级联查询
  8. Linux下创建指定路径下的文件夹/文件,通过get_option()传递路径
  9. javascrip执行字符串里面的函数
  10. 关于android的各种disk images(看过的讲android image比较细致的好文)
  11. 内存管理之memblock探寻
  12. AJAX框架大全 (AJAX Frameworks)
  13. 微信小程序Demo详解
  14. 阿里字体小图标的使用
  15. couchbase导出mysql
  16. Python 实现Mac 屏幕截图
  17. 如何提高专业英文阅读能力
  18. wsl(Windows Subsystem for Linux)启动多个子系统和设置默认启动子系统
  19. JavaWeb课程设计(风险地区查询系统)
  20. conda env create -f environment.yml 出现Package XX conflicts for:

热门文章

  1. 用Java编写程序实现从键盘读入学生成绩,找出最高分,并输出学生成绩和学生的等级。
  2. 纹理的应用(凹凸贴图与法线贴图,三维噪声和三维纹理)
  3. 使用GCD 转自 Posted by 唐巧
  4. LORA+4G无线组网的方案
  5. vue中a的href写法
  6. 微信小程序字母索引菜单
  7. SAR,SHR,SAL,SHL区别
  8. 金蝶shr动态列表展示自定义字段
  9. 区块链和去中心化的弱点
  10. 福利:学生免费注册使用JB全家桶