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

次のセクションでは、RAML 1.0 で API 仕様を作成するときの作成者による一般的なエラーと、それらを解決するためのヒントについて説明します。

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

RAML 1.0 の仕様では、キーワードの ​schema​ と ​schemas​ が ​type​ と ​types​ に置き換えられました。​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

問題を解決するには、​schema​ と ​schemas​ を ​type​ と ​types​ に置き換えます。

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

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

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

#%RAML 1.0

title: Example API Spec

types:
 string:
   type: string

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

#%RAML 1.0

title: Example API Spec

types:
 customString:
   type: string

例と RAML NamedExample フラグメントに関するよくある誤解

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

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

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

    fragment.raml
    #%RAML 1.0 NamedExample
    myExample1:
        a: "b1"
        b: 1
    
    myExample2:
        a: "b2"
        b: 2

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

!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​ ノードで適用する必要があります。

["main"] 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
      ]

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

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

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

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

数値型の例は、​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

ペイロードで ​nil​ として定義されている型は無効

データ型が ​nil​ の型はペイロードで使用できません。

例 1

次の例では、​type​ の値は ​nil​ ではなく ​string​ にする必要があります。

#%RAML 1.0
title: test

types:
  MyType:
    type: nil
    example: “test”

例 2

次の例では、JSON スキーマで ​MyType​ を ​string​ として定義する必要があります。ただし、スキーマは空になります。

#%RAML 1.0
title: test

types:
  MyType:
    type: !include schema.json # schema.json is an empty file
    example: “test”

このような場合のエラーメッセージは ​should be null at …​​ になります。

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/json​ と ​application/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:
        ...
{
...
"assessments.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 node​。​minimum​ は、サポートされていないプロパティの名前です。​string​ に最小値はありません。 * Property invalidfacet not supported in a RAML 0.8 webApi node​。​invalidfacet​ は、RAML 仕様で定義されていないファセットの名前です。

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

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

  Obj:
    type: object
    properties:
      prop:
        type: Prop
#%RAML 1.0
title: Test
types:
  Prop:
    type: string

  Obj:
    type: object
    properties:
      prop:
        type: Prop
        required: false

無効な型の継承

type-inheritance エラーは主に、2 つの型を間違った方法でマージしている場合とサブタイプで弱い制約を定義している場合に発生します。

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

サブタイプで弱い制約を定義している

親型で定義されている制約よりも弱い制約を定義しているサブタイプは無効です。

次の例では、親型 MyType1 ですでに ​name​ プロパティが必須として定義されているにもかかわらず、サブタイプ MyType2 で省略可能なプロパティ ​name​ が文字列として定義されています。

#%RAML 1.0
title: test

types:
  MyType1:
    properties:
      name: string
  MyType2:
    type: MyType1
    properties:
      name?: string #invalid

このような場合のエラーメッセージは ​Resolution error: sub type has a weaker constraint for minItems than base type for minItems.​ になります。

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

このエラーは、存在しない型がヘッダーで指定されている場合に発生します。エラーを修正するには、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

URI パラメーターでスラッシュを使用している

スラッシュ (/) が含まれている URI パラメーターは無効です。

次の例では、URI パラメーター ​transaction-Date​ の ​example​ が原因でパーサーにエラーメッセージが表示されます。

#%RAML 1.0
title: test

/endpoint:
  uriParameters:
    transaction-Date:
      example: 01/02/2018

このような場合のエラーメッセージは ​Value '01/02/2018' of uri parameter must not contain '/' character.​ になります。

datetime​ 型の形式が無効

「rfc3339」または「rfc2616」が使用されていない ​datetime​ 型の形式は無効です。

次の例では、パーサーにエラーメッセージが表示されます。

#%RAML 1.0
title: test
types:
  MyType:
    type: datetime
    format: "rfc3338"

このような場合のエラーメッセージは ​Invalid format value for datetime, must be ‘rfc3339’ or ‘rfc2616’.​ になります。

RAML フラグメントプロジェクトの絶対パス

(!include /examples/200.json)​ のように、RAML フラグメントプロジェクトの絶対パスを使用して連動関係を追加すると、​「Resource /examples/200.json not found (リソース /examples/200.json が見つかりません)」​という検証エラーが発生します。

(!include ../examples/200.json)​ のように、必ず RAML フラグメントプロジェクトの相対パスを使用する必要があります。