RAML 0.8 API 仕様のよくある問題

2019 年 1 月 10 日の時点で、コードエディタ (Design Center の API Designer に用意されている 2 つのエディタのうちの 1 つ) は、それ以前に作成されている RAML API 仕様プロジェクトに対してより厳しい検証をデフォルトで行います。RAML 0.8 で書かれたパブリッシュ済みの API 仕様をコードエディタで開いたときに、違反 (赤) や警告 (オレンジ色) のメッセージが表示された場合は、メッセージの内容が RAML での問題を解決するのに役立つ可能性があります。

少なくとも 2020 年 1 月 10 日までは猶予期間が設けられていますが、それ以降は、違反メッセージを生成する API 仕様はパブリッシュできなくなります。

スキーマで予約済みの名前が使用されている

予約済み名前をスキーマ名として使用すると、エディタは次のメッセージを表示します。

‘schemaName’ cannot be used to name a custom schema

予約済みの名前としては、stringintegernumberobject などがあります。RAML 仕様で使用されている名前は、いずれもスキーマ名としては使用できません。

たとえば、次の API 仕様に対してエディタはメッセージを表示します。

#%RAML 0.8

title: Example API Spec

schemas:
 string:
   type: string

この問題を解決するには、スキーマ宣言で別の名前を使用します。

#%RAML 0.8

title: Example API Spec

schemas:
 customString:
   type: string

例の検証時の問題

ブール列挙の例で文字列データ型を使用していない

ブール列挙が文字列またはブール値のどちらであっても、例は文字列型でなければなりません。この違反の具体例として、次の API 仕様では例で間違ったデータ型を使用しています。

#%RAML 0.8
title: ExampleRAML
/nob:
  head:
    responses:
      204:
        headers:
          X-NOB-Exists:
            enum: [true, false]
            example: true

RAML 0.8 では、列挙値で文字列のみをサポートし、ブール値はサポートしません。また、上の RAML の例では、列挙のデータ型が宣言されていません。RAML 0.8 では、データ型が宣言されていない場合は string であると見なされます。

したがって、上の間違った例では、列挙の値を引用符で囲む必要があります。その理由は、例のデータ型を、例の対象となる要素と同じデータ型にする必要があるためです。

上の RAML 例の最後の 2 行は次のように記述しなければなりません。

...
            enum: ["true", "false"]
            example: "true"

必須プロパティを定義するスキーマの例で、そのプロパティを使用していない

必須プロパティを定義するスキーマの例では、そのプロパティを使用する必要があります。この問題の例で、次の API 仕様では、エンドポイント /order/{id} に対する応答を定義しています。この定義には get_order_response_schema.jsonget_order_response.json という 2 つのファイルが含まれています。

#%RAML 0.8
title: ExampleRAML
version: 1.0
...
/order:
  displayName: Orders API
  /create:
    ...

  /{id}:
    displayName: Get Order by OrderId
    description: This operation will get an order by order ID from Salesforce.
    get:
      description: This operation returns the order from Salesforce by Fulfillment Order ID, not by the Salesforce unique ID.
      responses:
        200:
          body:
            application/json:
              schema: !include get_order_response_schema.json
              example: !include get_order_response.json

get_order_response_schema.json ファイルでは sfOrderId プロパティを必須プロパティとして定義しています。

{
	"type":"object",
	"$schema": "http://json-schema.org/draft-03/schema",
	"id": "http://com.mulesoft.demo.orders.get.json.order",
	"required":false,
	"properties":{
      ...
      "sfOrderId": {
        "type":"string",
        "id": "http://com.mulesoft.demo.orders.create.json.get.sfOrderId",
        "required":true
      },
  ...

スキーマの例は get_order_response.json に記述されています。しかしながら、必須プロパティの名前が sOrderId と間違っています。

{
  "orderId": 14523,
  "sOrderId": "fadfead3524523",
  "sfAccountId": "fedfes3653635",
  "orderName": "Order From Manufacturing-Company, Inc.",
  "total": 174.92,
  "orderType": "E-Commerce Order",
  "description": "8 widgets",
  "orderDate": "04-03-2018"
}

スキーマの例でスキーマが定義するデータ型を使用していない

たとえば、次の API 仕様のスキーマでは title プロパティのデータ型をオブジェクトとして定義していますが、スキーマの例では配列が使用されています。

#%RAML 0.8
title: ExampleRAML
schemas:
  - presentation: |
      {  "$schema": "http://json-schema.org/draft-03/schema",
         "type": "object",
         "properties": {
           "title":  { "type": "string" }
         }
      }

/presentations: &presentations
  type: { typedCollection: { schema: presentation } }
  get:
    responses:
      200:
       body:
         application/json:
           example: |
             [
              {
                  "title": "Presentation Video"
              },
              {
                  "title": "Environment Spec Report"
              }
              ]

ブールの例で値に 0 や 1 を使用している

ブールの例で使用できる値は「true」または「false」です。次の API 仕様では、フォームパラメータ is_public の例で使用されている値が間違っています。

#%RAML 0.8
title: ExampleRAML

/upload:
  post:
    description: |
      Upload a photo
    body:
      multipart/form-data:
        formParameters:
          title:
            description: The title of the photo.
          is_public:
            type: boolean
            example: 1

例にプロパティが含まれていない

例に対象となる型のプロパティが含まれていないと、エディタは違反メッセージを表示します。

should have required property 'property name'

次の API 仕様では、age プロパティが例に含まれていません。

#%RAML 0.8
title: Example API Spec

/clients:
  get:
    responses:
      200:
        body:
          application/json:
            schema: |
              {
                "$schema": "http://json-schema.org/draft-03/schema",
                "properties": {
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "age": {
                      "type": "number",
                      "required": true
                    }
                },
                "required": false,
                "type": "object"
              }
            example:
              firstName: John
              lastName: Smith

例にプロパティを追加するか、または型宣言でプロパティを省略可能として宣言してください。

次のケースでは、プロパティが例に追加されています。

#%RAML 0.8
title: Example API Spec

/clients:
  get:
    responses:
      200:
        body:
          application/json:
            schema: |
              {
                "$schema": "http://json-schema.org/draft-03/schema",
                "properties": {
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "age": {
                      "type": "number",
                      "required": true
                    }
                },
                "required": false,
                "type": "object"
              }
            example:
              firstName: John
              lastName: Smith
              age: 30

次のケースでは、プロパティが省略可能として宣言されています。

#%RAML 0.8
title: Example API Spec

/clients:
  get:
    responses:
      200:
        body:
          application/json:
            schema: |
              {
                "$schema": "http://json-schema.org/draft-03/schema",
                "properties": {
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "age": {
                      "type": "number",
                      "required": false
                    }
                },
                "required": false,
                "type": "object"
              }
            example:
              firstName: John
              lastName: Smith

title ノードの値がない

title ノードでは、次のように値を省略することはできません。

#%RAML 0.8
title:

要素の例で RAML 要素のデータ型を使用していない

すべてのケースにおいて、例のデータ型は、例の対象となる要素と同じでなければなりません。

次の間違った API 仕様では、クエリパラメータを文字列として定義していますが、例では整数が使用されています。

#%RAML 0.8
title: ExampleRAML
/books:
  get:
    queryParameters:
      publicationYear:
        type: string
        example: 2016

JSON スキーマ内部の参照パスが無効である

JSON スキーマで $ref キーワードを使用する場合、指定するパスはスキーマのルートから始まっていなければなりません。たとえば、次のスキーマで input2 プロパティに対して使用されている $ref キーワードでは、input プロパティを参照するためのパスが間違っています。

#%RAML 0.8
title: ExampleRAML
version: v1
schemas:
- authCodeResponse : |
    {
      "$schema": "http://json-schema.org/draft-04/schema",
      "properties": {
        "input": {
          "type": "string"
        },
        "input2": {
          "$ref": "input"
        }
      },
       "type": "object"
    }

パスはスキーマのルートレベルから始まり、ツリー構造を下がって行かなければなりません。次のスキーマの例では、同じ $ref キーワードで正しいパスが使用されています。

{
      "$schema": "http://json-schema.org/draft-04/schema",
      "properties": {
        "input": {
          "type": "string"
        },
        "input2": {
          "$ref": "#/properties/input"
        }
      },
       "type": "object"
    }

使用されない URI パラメータを宣言している

API 仕様で宣言した URI パラメータが仕様内で使用されていない場合、エディタは次の警告メッセージを表示します。

unused uri parameter “parameter”

ベース URI パラメータとして宣言されているパラメータが使用されていない場合は、エディタは次の警告メッセージを表示します。

unused base uri parameter “parameter”

たとえば、次の API 仕様により 2 つの警告メッセージが表示されます。

unused uri parameter "unusedParam"
unused base uri parameter "unusedUriParam"
#%RAML 0.8
title: test

baseUri: http://param.raml/a/{baseUriParam1}/{nonExists}/{baseUriParam2}

baseUriParameters:
 baseUriParam1:
    type: string
 baseUriParam2:
    type: string
 unusedParam:
    type: string

/endpoint/{uriParam1}/{nonExistsUri}:
 uriParameters:
   uriParam1:
     type: string
   unusedUriParam:
     type: string

警告メッセージは、単純にこれらのパラメーターを宣言している行を削除するだけで表示されなくなります。

#%RAML 0.8
title: test

baseUri: http://param.raml/a/{baseUriParam1}/{nonExists}/{baseUriParam2}

baseUriParameters:
 baseUriParam1:
   type: string
 baseUriParam2:
     type: string

/endpoint/{uriParam1}/{nonExistsUri}:
 uriParameters:
   uriParam1:
     type: string

ペイロードのメディア種別を宣言していない

ペイロードの宣言でメディア種別が宣言されていないと、エディタは次のメッセージを表示します。

Payload media type is mandatory

たとえば、次の API 仕様に対してエディタはこのメッセージを表示します。

#%RAML 0.8
title: Example API Spec
/media:
 get:
   responses:
     200:
       body:
         type: string

この問題の解決法は 2 つあります。

  • ペイロード宣言でメディア種別をローカルに宣言する。

    #%RAML 0.8
    title: Example API Spec
    /media:
     get:
       responses:
         200:
           body:
            application/json:
             type: string
  • API 仕様でデフォルトのメディア種別をグローバルに指定する。

    #%RAML 0.8
    title: Example API Spec
    
    mediaType: application/json
    
    /media:
     get:
       responses:
         200:
           body:
             type: string

次の例では、グローバル宣言とローカル宣言の両方を使用しています。このケースでは、mediaType ノードは application/jsonapplication/xml を受け入れ可能なメディア種別として定義しています。最初の種別である Person は、どちらのメディア種別であっても構わずに本文を返します。2 番目の種別である Another は、ローカル宣言でグローバル宣言を上書きし、JSON の本文のみを返します。

#%RAML 0.8
title: New API
mediaType: [ application/json, application/xml ]
schemas:
  Person:
  Another:
/list:
  get:
    responses:
      200:
        body: Person
/send:
  post:
    body:
      application/json:
        schema: Another

!include タグを使用してフラグメントを参照していない

API 仕様で uses キーを使用してフラグメントを参照していると、エディタは次のメッセージを表示します。

Fragments must be imported by using '!include'

uses キーを使用してライブラリを適用していない

API 仕様で !include タグを使用してライブラリを適用していると、エディタは次のメッセージを表示します。

Libraries must be applied by using 'uses'

構文の問題

無効な JSON を含むスキーマが含まれている

schemas プロパティの値に含まれるファイルには、有効な JSON が必要です。

最初の例には appSwitcher.json というスキーマが含まれています。しかし、2 番目の例では、JSON にエラーがあり、最後の値の末尾が引用符であるべきところがカンマになっています。

#%RAML 0.8
title: ExampleRAML
schemas:
  - appSwitcher: !include schemas/appSwitcher.json
{
  "appMenuItems" : [
    {
      "type" : "Tabset" ,
      "content" : null ,
      "icons" : null ,
      "colors" : null ,
      "label" : "Call Center" ,
      "url" : "/home/home.jsp?tsid=02uxx00000056Sr"
    } , {
      "type" : "Tabset" ,
      "content" : null ,
      "icons" : null ,
      "colors" : null ,
      "label" : "Community" ,
      "url" : "/home/home.jsp?tsid=02uxx00000056Sw"
    } , {
      "type" : "Tabset" ,
      "content" : null ,
      "icons" : null ,
      "colors" : null ,
      "label" : "App Launcher" ,
      "url" : "/app/mgmt/applauncher/appLauncher.apexp?tsid=02uxx00000056Sx,
    }
  ]
}

JSON スキーマの例で無効な JSON を使用している

次の API 仕様では JSON スキーマの例が間違っていますが、有効な JSON を使用しなければなりません。

#%RAML 0.8
title: ExampleRAML
...
/api:
  get:
    responses:
      200:
        body:
          application/json:
            schema:
              {
                "type": "object",
                "required": true,
                "$schema": "http://json-schema.org/draft-03/schema",
                "properties": {
                  "a": {
                    "type": "boolean",
                    "required": true
                  }
                }
              }
            example:
              {
                "a: {
                  "a": ""
                }

ファセットが YAML マップを必要としている場合に YAML マップを提供していない

値としてマップが必要であるとして RAML 0.8 仕様でファセットが記述されており、API 仕様でマップが提供されていない場合、エディタにメッセージ「YAML map expected」が返されます。

次に、エラーの例を示します。

#%RAML 0.8
title: Test
version: 1.0
securitySchemes:
  basic:
    type: Basic Authentication
    settings:

エラーの修正方法は 2 つあります。

  • マップを値として提供する。

    #%RAML 0.8
    title: Test
    version: 1.0
    securitySchemes:
      basic:
        type: Basic Authentication
        settings:
          requestTokenUri: https://api.mysampleapi.com/1/oauth/request_token
  • マップを必要とするファセット (この場合は settings) を削除する。

    #%RAML 0.8
    title: Test
    version: 1.0
    securitySchemes:
      basic:
        type: Basic Authentication

サポートされないプロパティを使用している

このエラーは未定義のファセットを使用した場合に発生します。

エラーメッセージの例

Property invalidfacet not supported in a RAML 0.8 webApi nodeinvalidfacet は、RAML 仕様で定義されていないファセットの名前です。

このエラーが生成される例を次に示します。

Table 1. 間違った例と正しい例
間違い 正しい
#%RAML 0.8
title: Test
invalidfacet:
version:
#%RAML 0.8
title: Test
version:

未定義の型をヘッダーで宣言している

このエラーは、存在しない型がヘッダーで指定されている場合に発生します。

エラーメッセージ

Cannot declare unresolved parameter

次の間違った例では、ヘッダー myHeader の値に入力ミスがあります。string ではなく strang と指定されています。

Table 2. 間違った例と正しい例
間違い 正しい
#%RAML 0.8
title: test

/endpoint:
  post:
    headers:
      myHeader: strang
#%RAML 0.8
title: test

/endpoint:
  post:
    headers:
      myHeader: string

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub