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


    RAML是Restful API Modeling Language的缩写,是用来描述API信息的文档。

    创建一个.raml后缀的文件,用Atom打开。

    基本用法

    #%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:

    以上,

    ● 类型/users:看作是resource,也就是以/开始,:结尾,而且resource是嵌套存在的
    ● queryParameters描述查询字符串

    接下来把.raml转换成html格式,有一个开源的项目。

    → 参考:https://github.com/raml2html/raml2html
    → 全局安装:npm i -g raml2html
    → .raml文件所在文件夹内打开命令窗口,输入:raml2html example.raml > example.html

    就是这么个效果:

    Body Parameters

    POST请求,通常把参数放到body中传递,在RAML中如何描述呢?

    在Body中的参数传递有很多方式,需要在Headers下的Content-Type中设置。Content-Type这个key可能的值包括:multipart/form-data, application/json, application/x-www-form-urlencoded等等。

    1、通过multipart/form-data

    /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文件引入进来

    2、通过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

  • 相关阅读:
    Core的学习三:容器的使用实例
    Core的学习二:【四步完成】.Net Core中Log4net的使用,配置,【框架.NET5】
    C#7 的一些新语法
    C#6 的一些新语法
    Core的学习一:Core部署在IIS下
    C# 特性【Attribute】【什么是特性?以及特性的一些修饰】
    C#反射
    泛型 -Generic 【why,原理,与普通方法,object的性能对比如何?泛型类、泛型方法、泛型接口、泛型委托,泛型约束,协变 逆变,泛型缓存】
    springboot通过切面编程实现系统请求操作日志记录
    Linux 【安装配置VM虚拟机】
  • 原文地址:https://www.cnblogs.com/darrenji/p/5198524.html
Copyright © 2020-2023  润新知