使用RAML描述API文檔信息的一些用法整理

 

RAML是Restful API Modeling Language的縮寫,是用來描述API信息的文檔。html

 

建立一個.raml後綴的文件,用Atom打開。git

 

基本用法

 

#%RAML 0.8
  title: Book API
  baseUri: http://api.book.com/{version}
  version: v1
  /users:
    /authors:
      /{authorname}:
    /books:
      get:
        queryParameters:
          author:
            displayName: Author
            type: string
            description: An author's full name
            example: Mary
            required: false
          publicationYear:
            displayName: Pub Year
            type: number
            description: The year released for the first time
            example: 1984
            required: false
          rating:
            displayName: Rating
            type: number
            description: Average rating
            required: false
          isBn:
            displayName: ISBN
            type: string
            minLength: 10
            example: 0321736079
      put:
        queryParameters:
          access_token:
            displayName: Access Token
            type: string
            description: Token giving you permission to make call
            required: true
      post:
      /{bookTitle}:
        get:
          description: Retrieve a specific book title
          responses:
            200:
              body:
                application/json:
                  example: |
                    {
                      "data":{
                        "id": "SbBGk",
                        "title": "its the title",
                        "descritpion": null
                      },
                      "success": true,
                      "status": 200
                    }

        put:
        delete:
        /author:
          get:
        /publiser:
          get:

 

以上,github

● 類型/users:看做是resource,也就是以/開始,:結尾,並且resource是嵌套存在的
● queryParameters描述查詢字符串web

 

接下來把.raml轉換成html格式,有一個開源的項目。npm

 

→ 參考:https://github.com/raml2html/raml2html
→ 全局安裝:npm i -g raml2html
→ .raml文件所在文件夾內打開命令窗口,輸入:raml2html example.raml > example.htmljson

 

就是這麼個效果:api

Body Parameters

 

POST請求,一般把參數放到body中傳遞,在RAML中如何描述呢?數組

 

在Body中的參數傳遞有不少方式,須要在Headers下的Content-Type中設置。Content-Type這個key可能的值包括:multipart/form-data, application/json, application/x-www-form-urlencoded等等。app

 

一、經過multipart/form-datadom

 

/file-content:
  description: The file to be reproduced by the client
  get:
    description: Get the file content
    responses:
      200:
        body:
          binary/octet-stream:
            example:
              !include heybulldog.mp3
  post:
    description: |
       Enters the file content for an existing song entity.

       Use the "binary/octet-stream" content type to specify the content from any consumer (excepting web-browsers).
       Use the "multipart-form/data" content type to upload a file which content will become the file-content
    body:
      binary/octet-stream:
      multipart/form-data:
        formParameters:
          file:
            description: The file to be uploaded
            required: true
            type: file

 

以上,

● Content-Type能接受的類型是binary/octet-stream或multipart/form-data
● 對於multipart/form-data類型,鍵值數據放在了formParameters中
● !include heybulldog.mp3表示把heybulldog.mp3文件引入進來

 

二、經過JSON Shema

 

JSON Shema用來描述JSON格式。

 

爲何須要JSON Schema呢?

 

舉個例子:

 

{
    "id":1,
    "name":"a green door",
    "price":12.50,
    "tags":["home", "green"]
}

 

咱們可能會問:

● 什麼是id
● name字段必須嗎
● price的值能夠是0嗎
● tags所表明的數組元素是string類型嗎?


JSON Schema就是解決這些問題的。

 

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object"
}

 

以上,

● $schema表示當前JSON Shema所採用的版本
● type字段是必須的,是object類型

 

接着,對id字段約束。

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        }
    },
    "required": ["id"]
}

 

對name字段約束。

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        }
    },
    "required": ["id", "name"]
}

 

對price字段約束。

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        },
        "price": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        }
    },
    "required": ["id", "name", "price"]
}

 

對tags字段約束。

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        },
        "price": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        },
        "tags": {
            "type": "array",
            "items": {
                "type": "string"
            },
            "minItems": 1,
            "uniqueItems": true
        }
    },
    "required": ["id", "name", "price"]
}

 


數組如何用JSON Schema描述呢?

 

[
    {
        "id": 2,
        "name": "An ice sculpture",
        "price": 12.50,
        "tags": ["cold", "ice"],
        "dimensions": {
            "length": 7.0,
            "width": 12.0,
            "height": 9.5
        },
        "warehouseLocation": {
            "latitude": -78.75,
            "longitude": 20.4
        }
    },
    {
        "id": 3,
        "name": "A blue mouse",
        "price": 25.50,
        "dimensions": {
            "length": 3.1,
            "width": 1.0,
            "height": 1.0
        },
        "warehouseLocation": {
            "latitude": 54.4,
            "longitude": -32.7
        }
    }
]

 

用JSON Shema描述就是這樣:

 

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product set",
    "type": "array",
    "items": {
        "title": "Product",
        "type": "object",
        "properties": {
            "id": {
                "description": "The unique identifier for a product",
                "type": "number"
            },
            "name": {
                "type": "string"
            },
            "price": {
                "type": "number",
                "minimum": 0,
                "exclusiveMinimum": true
            },
            "tags": {
                "type": "array",
                "items": {
                    "type": "string"
                },
                "minItems": 1,
                "uniqueItems": true
            },
            "dimensions": {
                "type": "object",
                "properties": {
                    "length": {"type": "number"},
                    "width": {"type": "number"},
                    "height": {"type": "number"}
                },
                "required": ["length", "width", "height"]
            },
            "warehouseLocation": {
                "description": "Coordinates of the warehouse with the product",
                "$ref": "http://json-schema.org/geo"
            }
        },
        "required": ["id", "name", "price"]
    }
}

 

RAML也用到了JSON Shema,就像這樣:

body:
  application/json:
    schema: |
      {
        "type": "object",
        "$schema": "http://json-schema.org/draft-03/schema",
        "id": "http://jsonschema.net",
        "required": true,
        "properties": {
          "songTitle": {
            "type": "string",
            "required": true
          },
          "albumId": {
            "type": "string",
            "required": true,
            "minLength": 36,
            "maxLength": 36
          }
        }
      }
    example: |
      {
        "songId": "550e8400-e29b-41d4-a716-446655440000",
        "songTitle": "Get Lucky",
        "albumId": "183100e3-0e2b-4404-a716-66104d440550"
      }

 

schemas

 

每一個資源都有本身的schema,是否能夠把全部資源的schema合併到同一個地方呢?

 

RAML提供了schemas字段。

schemas:
 - song: |
    {
      "type": "object",
      "$schema": "http://json-schema.org/draft-03/schema",
      "id": "http://jsonschema.net",
      "required": true,
      "properties": {
        "songTitle": {
          "type": "string",
          "required": true
        },
        "albumId": {
          "type": "string",
          "required": true,
          "minLength": 36,
          "maxLength": 36
        }
      }
    }

 

按以下引用:

body:
  application/json:
    schema: song
    example: |
      {
        "songId": "550e8400-e29b-41d4-a716-446655440000",
        "songTitle": "Get Lucky",
        "albumId": "183100e3-0e2b-4404-a716-66104d440550"
      }

 

Resource Types資源類型

 

每一個資源通有類似的部分,可否把這些類似的部分提取抽象出來呢?

 

假設有2個資源:/resources和/{resourceId}

#%RAML 0.8
title:

/resources:
  get:
  post:
  /{resourceId}:
    get:
    put:
    delete:

 

以上,resource大體能夠分紅針對集合和針對個體的,因此,在RAML中經過resourceTypes對資源進行分類,有這樣的表達方式:

resourceTypes:
  - collection:
      get:
      post:
  - collection-item:
      get:

 

因而collection類型能夠寫成這樣:

resourceTypes:
  - collection:
      description: Collection of available <<resourcePathName>> in Jukebox.
      get:
        description: Get a list of <<resourcePathName>>.
        responses:
          200:
            body:
              application/json:
      post:
        description: |
          Add a new <<resourcePathName|!singularize>> to Jukebox.
        queryParameters:
          access_token:
            description: "The access token provided by the authentication application"
            example: AABBCCDD
            required: true
            type: string
        body:
          application/json:
            schema: <<resourcePathName|!singularize>>
        responses:
          200:
            body:
              application/json:
                example: |
                    { "message": "The <<resourcePathName|!singularize>> has been properly entered" }

 

以上,

● <<resourcePathName>>是佔位符,相似表示songs
● 另外<<resourcePath>>是佔位符,相似表示/songs
● <<resourcePathName|!singularize>>是佔位符,相似表示song

● <<resourcePathName|!pluralize>>是佔位符,相似表示songs


而後這樣使用:

/songs:
  type: collection
  get:
    queryParameters:
      songTitle:
        description: "The title of the song to search (it is case insensitive and doesn't need to match the whole title)"
        required: true
        minLength: 3
        type: string
        example: "Get L"
    responses:
      200:
        body:
          application/json:
            example: |
              "songs": [
                  {
                    "songId": "550e8400-e29b-41d4-a716-446655440000",
                    "songTitle": "Get Lucky"
                  },
                  {
                    "songId": "550e8400-e29b-41d4-a716-446655440111",
                    "songTitle": "Loose yourself to dance"
                  },
                  {
                    "songId": "550e8400-e29b-41d4-a716-446655440222",
                    "songTitle": "Gio sorgio by Moroder"
                  }
                  ]
  post:
    body:
      application/json:
          example: |
            {
              "songId": "550e8400-e29b-41d4-a716-446655440000",
              "songTitle": "Get Lucky",
              "albumId": "183100e3-0e2b-4404-a716-66104d440550"
            }

 

collection-item類型能夠寫成這樣:

resourceTypes:
  - collection:
  ...

  - collection-item:
      description: Entity representing a <<resourcePathName|!singularize>>
      get:
        description: |
          Get the <<resourcePathName|!singularize>>
          with <<resourcePathName|!singularize>>Id =
          {<<resourcePathName|!singularize>>Id}
        responses:
          200:
            body:
              application/json:
          404:
            body:
              application/json:
                example: |
                  {"message": "<<resourcePathName|!singularize>> not found" }  

 

而後這樣使用:

/songs:
  ...
  /{songId}:
    type: collection-item
    get:
      responses:
        200:
          body:
            application/json:
              example: |
                {
                  "songId": "550e8400-e29b-41d4-a716-446655440000",
                  "songTitle": "Get Lucky",
                  "duration": "6:07",
                  "artist": {
                    "artistId": "110e8300-e32b-41d4-a716-664400445500"
                    "artistName": "Daft Punk",
                    "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg"
                  },
                  "album": {
                    "albumId": "183100e3-0e2b-4404-a716-66104d440550",
                    "albumName": "Random Access Memories",
                    "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg"
                  }
                }

 

以上,
● 在resourceTypes中的謂詞get,post等,能夠在具體的resource中進行從新定義
● 在resrouce級別,經過type: collection-item或type: collection與resourceTypes對應

 

Parameters

 

以上,resourceTypes字段所表明的是一個對集合和個體類型相同操做的一個封裝,在這些操做中,在這些請求響應中,有時須要經過example字段來舉例,一般這樣寫:

example: |
    {
        ...
    }

或者

example: |
[
    {
    
    },
    {
    
    }
]

 

但在RAML中,爲咱們提供了<<exampleCollection>>和<<exampleItem>>佔位符分別表示集合和個體。

resourceTypes:
  - collection:
      description: Collection of available <<resourcePathName>> in Jukebox.
      get:
        description: Get a list of <<resourcePathName>>.
        responses:
          200:
            body:
              application/json:
                example: |
                  <<exampleCollection>>
      post:
        description: |
          Add a new <<resourcePathName|!singularize>> to Jukebox.
        queryParameters:
          access_token:
            description: "The access token provided by the authentication application"
            example: AABBCCDD
            required: true
            type: string
        body:
          application/json:
            schema: <<resourcePathName|!singularize>>
            example: |
              <<exampleItem>>
        responses:
          200:
            body:
              application/json:
                example: |
                  { "message": "The <<resourcePathName|!singularize>> has been properly entered" }
  - collection-item:
      description: Entity representing a <<resourcePathName|!singularize>>
      get:
        description: |
          Get the <<resourcePathName|!singularize>>
          with <<resourcePathName|!singularize>>Id =
          {<<resourcePathName|!singularize>>Id}
        responses:
          200:
            body:
              application/json:
                example: |
                  <<exampleItem>>
          404:
            body:
              application/json:
                example: |
                  {"message": "<<resourcePathName|!singularize>> not found" }

 

在資源resource部分一般這樣調用:

/songs:
    type:
        collection:
            exampleCollection: |
                [
                    ...
                ]
    /{songId}:
        type:
            collection-item: 
                exampleItem: |
                {
                    ...
                }

 

具體來講,相似這樣:

/songs:
  type:
    collection:
      exampleCollection: |
        [
          {
            "songId": "550e8400-e29b-41d4-a716-446655440000",
            "songTitle": "Get Lucky"
          },
          {
            "songId": "550e8400-e29b-41d4-a716-446655440111",
            "songTitle": "Loose yourself to dance"
          },
          {
            "songId": "550e8400-e29b-41d4-a716-446655440222",
            "songTitle": "Gio sorgio by Morodera"
          }
        ]
      exampleItem: |
        {
          "songId": "550e8400-e29b-41d4-a716-446655440000",
          "songTitle": "Get Lucky",
          "albumId": "183100e3-0e2b-4404-a716-66104d440550"
        }
  get:
    queryParameters:
      songTitle:
        description: "The title of the song to search (it is case insensitive and doesn't need to match the whole title)"
        required: true
        minLength: 3
        type: string
        example: "Get L"
  /{songId}:
    type:
      collection-item:
        exampleItem: |
          {
            "songId": "550e8400-e29b-41d4-a716-446655440000",
            "songTitle": "Get Lucky",
            "duration": "6:07",
            "artist": {
              "artistId": "110e8300-e32b-41d4-a716-664400445500"
              "artistName": "Daft Punk",
              "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg"
            },
            "album": {
              "albumId": "183100e3-0e2b-4404-a716-66104d440550",
              "albumName": "Random Access Memories",
              "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg"
            }
          }

 

Includes

 

能夠把一些example放到單獨的文件,而後經過!include關鍵字來引用這些文件。

 

/songs:
  type:
    collection:
      exampleCollection: !include jukebox-include-songs.sample
      exampleItem: !include jukebox-include-song-new.sample
  /{songId}:
    type:
      collection-item:
        exampleItem: !include jukebox-include-song-retrieve.sample

 

traits

 

如何描述查詢、排序、分頁呢?

 

traits:
  - searchable:
      queryParameters:
        query:
          description: |
            JSON array [{"field1","value1","operator1"},{"field2","value2","operator2"},...,{"fieldN","valueN","operatorN"}] <<description>>
          example: |
            <<example>>aml
            
  - orderable:
      queryParameters:
        orderBy:
          description: |
            Order by field: <<fieldsList>>
          type: string
          required: false
        order:
          description: Order
          enum: [desc, asc]
          default: desc
          required: false
  - pageable:
      queryParameters:
        offset:
          description: Skip over a number of elements by specifying an offset value for the query
          type: integer
          required: false
          example: 20
          default: 0
        limit:
          description: Limit the number of elements on the response
          type: integer
          required: false
          example: 80
          default: 10    

 

按以下使用這些trait。

/songs:
  type:
    collection:
      exampleCollection: !include jukebox-include-songs.sample
      exampleItem: !include jukebox-include-song-new.sample
  get:
    is: [
          searchable: {description: "with valid searchable fields: songTitle", example: "[\"songTitle\", \"Get L\", \"like\"]"},
          orderable: {fieldsList: "songTitle"},
          pageable
        ]

 

另外,schema也能夠放到單獨的文件中,而後經過!include引用。

 

schemas:
 - song: !include jukebox-include-song.schema
 - artist: !include jukebox-include-artist.schema
 - album: !include jukebox-include-album.schema

 

resourceTypes也能夠放到單獨的文件中:

resourceTypes: !include jukebox-includes-resourceTypes.inc

相關文章
相關標籤/搜索