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

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

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

type または types キーワードではなく schema または schemas を使用している

RAML 1.0 の仕様では、キーワードの schemaschemastypetypes に置き換えられました。schema または schemas を使用すると、エディタは次のいずれかの警告メッセージを表示します。

‘schema' keyword it's deprecated for 1.0 version, should use 'type' instead
'schemas' keyword it's deprecated for 1.0 version, should use 'types' instead

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

#%RAML 1.0
title: Incorrect API with schema and schemas

schemas:
 User:
   type: object
   properties:
     firstname: string
     lastname:  string
     age:       number

/users/{id}:
 get:
   responses:
     200:
       body:
         application/json:
           schema: User

問題を解決するには、schemaschemastypetypes に置き換えます。

#%RAML 1.0
title: Correct API with type and types

types:
 User:
   type: object
   properties:
     firstname: string
     lastname:  string
     age:       number

/users/{id}:
 get:
   responses:
     200:
       body:
         application/json:
           type: User

型で予約済みの名前を使用している

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

‘typeName’ cannot be used to name a custom type

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

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

#%RAML 1.0

title: Example API Spec

types:
 string:
   type: string

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

#%RAML 1.0

title: Example API Spec

types:
 customString:
   type: string

名前付きの例での問題

名前付きの例を !include タグで参照する際のよくある問題を回避するには、次の 2 つのガイドラインに従ってください。

  • 次に示すように、API 仕様では examples ファセットを使用し、!include タグを 1 つだけ使用してください。

    #%RAML 1.0
    title: test
    types:
     A:
        properties:
           a: string
           b: integer
        examples: !include fragment.raml
  • NamedExample フラグメントでは、1 つの例を含む次のフラグメントのように、各例が名前と値で構成されるようにしてください。

    #%RAML 1.0 NamedExample
    myExample:
        a: "b"
        b: 1

名前付きの例の使用方法についての詳細は、「名前付きの例に関するガイド」を参照してください。

例に名前を 2 回付けている

例に名前が 2 回付けられている場合、エディタに次のメッセージが表示されます。

should have required property '<name-of-property>'

たとえば、仕様でプロパティ firstName を定義しており、例に名前 someName を指定することで NamedExample フラグメントにリンクしているとします。

#%RAML 1.0
title: Example API Spec
/tiers:
 post:
   body:
     application/json:
       properties:
         firstName: string
       examples:
         someName: !include ex.raml

また、NamedExample フラグメントでも例に名前 someFragmentName を指定しているとします。

#%RAML 1.0 NamedExample
someFragmentName:
  firstName: Martin Gutierrez

この場合、パーサーが someFragmentName をプロパティの名前として解釈するため、エディタに次のメッセージが表示されます。

should have required property 'firstName'

この種類の問題を解決するには、仕様の examples ファセット内の名前または NamedExample フラグメント内の名前を削除します。

NamedExample フラグメントから名前を削除する場合、フラグメント内の宣言から単語「NamedExample」を削除する必要があります。たとえば、上記の状況で使用されている NamedExample フラグメントを次のように変更します。

#%RAML 1.0
firstName: Martin Gutierrez

!include ステートメントのファイル名にハッシュ記号付きの参照を付加している

名前付きファイルでは、ファイル名の後にハッシュ記号と場所への参照を付加することはできません。次のケースでは、IncrementType.raml#increment は無効なリンクです。

#%RAML 1.0 DataType

type: object
properties:
  startValue: integer
  endValue: integer
  exclusiveEndValue: boolean
  range:
    type: array
    items: !include IncrementType.raml#increment

API 仕様にこの違反があり、実際にはコメントを付加しようとしていた場合には、# 記号の前にスペースを入れてください。ファイル内の要素を参照しようとしていた場合には、このような参照は許可されません。内部要素への参照は、XSD スキーマと JSON スキーマでのみ有効です。

JSON の例における中括弧と大括弧の使い方が正しくない

中括弧と大括弧の間違った使い方はたくさんあります。次にその一例を示します。JSON キー/値ペアグループの配列が不適切に中括弧で括られています。

#%RAML 1.0
title: ExampleRAML
...
/rooms:
  displayName: rooms
  get:
    description: get all rooms
    responses:
      200:
        body:
          application/json:
            example: |
             {
               [{
                "Name": "Superior King",
                "Number": "201",
                "Property": "SE030",
                "Status": "Clean"
                },
                {
                "Name": "Junior Suite",
                "Number": "202",
                "Property": "NO131",
                "Status": "Clean"
                }]
              }

この例をオブジェクトとして定義するつもりであれば、キーが必要です。

#%RAML 1.0
title: ExampleRAML
...
/rooms:
  displayName: rooms
  get:
    description: get all rooms
    responses:
      200:
        body:
          application/json:
            example:
            {
    	      "some_key": [
                {
                  "Name": "Superior King",
          	  "Number": "201",
          	  "Property": "SE030",
          	  "Status": "Clean"
          	},
          	{
          	  "Name": "Junior Suite",
          	  "Number": "202",
          	  "Property": "NO131",
          	  "Status": "Clean"
          	}
              ]
            }

この例を配列として定義するつもりであれば、外側の中括弧を削除する必要があります。

#%RAML 1.0
title: ExampleRAML
...
/rooms:
  displayName: rooms
  get:
    description: get all rooms
    responses:
      200:
        body:
          application/json:
            example:
            [
                {
                  "Name": "Superior King",
          	  "Number": "201",
          	  "Property": "SE030",
          	  "Status": "Clean"
          	},
          	{
          	  "Name": "Junior Suite",
          	  "Number": "202",
          	  "Property": "NO131",
          	  "Status": "Clean"
          	}
            ]

type ノードを使用してライブラリを適用している

RAML 1.0 仕様で説明したように、ライブラリは uses ノードで適用する必要があります。

["マスタ"] RAML または RAML フラグメントファイルのルートにおいてのみ、省略可能な uses ノードを使用してライブラリをいくつでも適用できます。`use`s ノードの値は、キー/値ペアのマップです。キーはライブラリ名または名前空間として扱われ、値は RAML ライブラリファイルの場所 (通常は外部の RAML ライブラリフラグメントドキュメント) でなければなりません。

type ノードを使用してライブラリを適用すると、エディタは次のメッセージを表示します。

Libraries must be applied by using 'uses'

したがって、financeDetail.raml ファイルがライブラリであるとすると、次の API 仕様は間違いになります。

#%RAML 1.0
title: ExampleRAML
...
/claims:
  /{claim-id}:
    patch:
      body:
        application/json:
          type: !include financeDetail.raml

正しくは次のようになります。

#%RAML 1.0
title: ExampleRAML
uses:
  lib: financeDetail.raml
/claims:
  /{claim-id}:
    patch:
      body:
        application/json:
          type: lib.myType

例の検証時の問題

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

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

should have required property 'property name'

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

#%RAML 1.0
title: Example API Spec

types:
 User:
   type: object
   properties:
     firstName: string
     lastName: string
     age: integer
   example:
     firstName: John
     lastName: Smith

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

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

#%RAML 1.0
title: Example API Spec

types:
 User:
   type: object
   properties:
     firstName: string
     lastName: string
     age: integer
   example:
     firstName: John
     lastName: Smith
     age: 49

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

#%RAML 1.0
title: Example API Spec

types:
 User:
   type: object
   properties:
     firstName: string
     lastName: string
     age?: integer
   example:
     firstName: John
     lastName: Smith

列挙のデータ型と一致しない列挙値を指定している

エディタは YAML 仕様に従って厳格な解析を行っているため、宣言されているデータ型に値を自動的にはキャストしません。この違反の具体例として、列挙の無効な宣言を示します。

type: string
enum: [1,2,3]

列挙のデータ型は string ですが、値はすべて整数です。エディタは YAML 仕様に従って厳格な解析を行うため、自動的に整数を string 値にはキャストしません。したがって、このケースでは型の宣言が間違っているため integer に直すか、または列挙値を引用符で囲む必要があります。

次の宣言も無効です。

type: string
enum: [
        "a",
        "b",
        "c",
        false,
        3.0
      ]

falseboolean 型ですが、値 3.0float 型です。エディタはどちらの値も string 値には変換しません。

次の 3 つの宣言は有効です。

type: string
enum: ["1","2","3"]
type: integer
enum: [1,2,3]
type: string
enum: [
        "a",
        "b",
        "c",
        "false",
        "3.0"
      ]
=== この違反は列挙だけではなく、string 値が期待される状況で integernil、または他のデータ型の値が指定されている場合に発生します。 ===

形式が指定されている場合に、数値型の例で型に対して正しくない形式を使用している

数値型の例は、format ノードで指定されている制限に準拠しなければなりません。この違反の具体例では、数値型 collection の形式として int8 が指定されています。しかしながら、例では 127 を超える値が使用されています。

#%RAML 1.0
title: ExampleRAML
types:
  collection:
    type: integer
    format: int8

/search:
  /code:
    get:
      body:
        application/json:
          type: collection
          example: 22342342

additionalProperties が false に設定されている状態で、宣言されていないプロパティが例に含まれている

型の例に型宣言で記述されていない 1 つまたは複数のプロパティが含まれていると、エディタは次のメッセージを表示します。

should NOT have additional properties

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

#%RAML 1.0
title: Example API Spec

types:
 User:
   type: object
   additionalProperties: false
   properties:
     firstName: string
     lastName: string
   example:
     firstName: John
     lastName: Smith
     age: 49

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

  • 例から余分なプロパティを削除する

    #%RAML 1.0
    title: Example API Spec
    
    types:
     User:
       type: object
       additionalProperties: false
       properties:
         firstName: string
         lastName: string
       example:
         firstName: John
         lastName: Smith
  • 型宣言にプロパティを追加する

    #%RAML 1.0
    title: Example API Spec
    
    types:
     User:
       type: object
       additionalProperties: false
       properties:
         firstName: string
         lastName: string
         age: integer
       example:
         firstName: John
         lastName: Smith
         age: 49
  • additionalProperties の値を true に変更するか、または additionalProperties の行を削除する (additionalProperties はデフォルトで true であるため)

    #%RAML 1.0
    title: Example API Spec
    
    types:
     User:
       type: object
       properties:
         firstName: string
         lastName: string
       additionalProperties: true
       example:
         firstName: John
         lastName: Smith
         age: 49

title ノードの値がない

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

#%RAML 1.0
title:

使用されない 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 1.0
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 1.0
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 1.0
title: Example API Spec
/media:
 get:
   responses:
     200:
       body:
         type: string

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

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

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

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

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

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

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

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

Fragments must be imported by using '!include'

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

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

Libraries must be applied by using 'uses'

構文の問題

応答例に無効な JSON が含まれている

応答メッセージの例として JSON ファイルが含まれている場合、ファイルの JSON は有効でなければなりません。次の違反のケースでは、応答コード 200 の応答例に !include ステートメントが含まれています。また、含まれているファイルの JSON では、最後のキー/値ペアの最後にカンマがあります。

#%RAML 1.0
title: ExampleRAML
...
/resume:
  description: "Gets candidate's resume."
  get:
    queryParameters:
       ...
    headers:
      ...
    responses:
      200:
        body:
          application/json:
            example: !include exampleResumeData-200.json
      500:
        ...
{
...
"assesments.characteristic.focusofattention.data"= "",
}

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

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

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

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

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

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

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

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

使用する型を定義していない

使用する型を最初に定義していない場合、エディタはメッセージ「Unresolved reference」を返します。

このエラーの例では、型 mytype が定義されていません。

#%RAML 1.0

title: test
/path:
  post:
    responses:
      200:
        body:
          application/json:
            type: mytype

この問題を解決するには、使用する型を定義します。

#%RAML 1.0

title: test
types:
  mytype: string
/path:
  post:
    responses:
      200:
        body:
          application/json:
            type: mytype

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

このエラーが発生するのは、特定のプロパティセットを持つとしてファセットまたはデータ型が定義されており、API 仕様でそのセットにないプロパティでファセットが定義されている場合です。このエラーは未定義のファセットを使用した場合も発生する可能性があります。

エラーメッセージの例: * Property minimum not supported in a RAML 1.0 stringScalarShape nodeminimum は、サポートされていないプロパティの名前です。string に最小値はありません。 * Property invalidfacet not supported in a RAML 0.8 webApi nodeinvalidfacet は、RAML 仕様で定義されていないファセットの名前です。

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

Table 1. 間違った例と正しい例
間違い 正しい
#%RAML 1.0
title: Test
types:
  top:
    type: string
    minimum: 1

#%RAML 1.0
title: Test
invalidfacet:
version:
#%RAML 1.0
title: Test
types:
  top:
    type: string
    minLength: 1

#%RAML 1.0
title: Test
version:

2 つの型を間違った方法でマージしている

この種類のエラーは、次のいずれかのアクションを実行しようとした場合に発生します。 * 定義済みの型を未定義の型とマージする * 2 つの未定義の型をマージする

また、誤った構文でマージを実行しようとした場合もこのエラーが発生します。

エラーメッセージの例

Resolution error: Incompatible types [class amf.plugins.domain.shapes.models.ScalarShape, class amf.plugins.domain.shapes.models.NodeShape]

次の例は 2 つの未定義の型をマージしようとしており、間違ったマージ構文を使用しています。エラーを解決するには、マージの前に型を定義し、マージ構文で括弧やカンマではなくパイプを使用します。

Table 2. 間違った例と正しい例
間違い 正しい
#%RAML 1.0
title: test
types:
  Device:
    type: [ Phone , Notebook ]
  Phone: string
  Notebook:
    type: object
    properties:
      manufacturer:
        type: string
#%RAML 1.0
title: test
types:
  Phone: string
  Notebook:
    type: object
    properties:
      manufacturer:
        type: string
  Device:
    type: Phone | Notebook

詳細は、RAML 1.0 仕様の「Union Types (Union 型)」を参照してください。

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

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

エラーメッセージ

Cannot declare unresolved parameter

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

Table 3. 間違った例と正しい例
間違い 正しい
#%RAML 1.0
title: test
types:
  SomeType: string
/endpoint:
  post:
    headers:
      MyHeader: someTypo
#%RAML 1.0
title: test
types:
  SomeType: string
/endpoint:
  post:
    headers:
      MyHeader: someType

Was this article helpful?

💙 Thanks for your feedback!

Edit on GitHub