wsdlopenapiapi-designtutorial

既存の SOAP を変えられない時に WSDL を OpenAPI へ変換する考え方

SOAPless Team7 min read

WSDL を OpenAPI に変換したい理由は、単なるドキュメント整備ではないことが多いです。

実際には、

  • 接続先の SOAP はベンダーや政府系で手を入れられない
  • でも利用側のチームには JSON / OpenAPI を渡したい
  • WSDL を読む担当者を増やしたくない

という事情で求められます。

つまり欲しいのは、「SOAP を OpenAPI っぽく説明すること」ではなく、「固定された SOAP の仕様を、利用側が扱える形にすること」です。

WSDL と OpenAPI の構造的な対応関係

変換を理解するために、まず WSDL と OpenAPI の構造的な対応を整理します。

WSDL の要素OpenAPI の対応要素
<wsdl:service>サーバー URL(servers
<wsdl:portType> + <wsdl:operation>パス + HTTP メソッド(paths
<wsdl:message>リクエスト/レスポンスボディ
<xsd:complexType>スキーマ(components/schemas
<xsd:element>プロパティ(properties
<soap:binding>該当なし(REST では不要)

OpenAPI が効くのは、この対応表を人間の頭の中だけで持たなくて済むからです。

利用側のチームにとって重要なのは、

  • リクエストとレスポンスの形
  • 認証の置き場所
  • エラーの見え方
  • テスト導線

であって、WSDL の複雑さそのものではありません。

手動変換の手順

以下の WSDL を例に、手動で OpenAPI 3.0 に変換してみましょう。

元の WSDL

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:tns="http://example.com/userservice"
                  targetNamespace="http://example.com/userservice">

  <wsdl:types>
    <xsd:schema targetNamespace="http://example.com/userservice">
      <xsd:complexType name="User">
        <xsd:sequence>
          <xsd:element name="id" type="xsd:int"/>
          <xsd:element name="name" type="xsd:string"/>
          <xsd:element name="email" type="xsd:string"/>
          <xsd:element name="department" type="xsd:string" minOccurs="0"/>
        </xsd:sequence>
      </xsd:complexType>

      <xsd:element name="GetUserRequest">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="userId" type="xsd:int"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="GetUserResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="user" type="tns:User"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </wsdl:types>

  <wsdl:message name="GetUserInput">
    <wsdl:part name="parameters" element="tns:GetUserRequest"/>
  </wsdl:message>

  <wsdl:message name="GetUserOutput">
    <wsdl:part name="parameters" element="tns:GetUserResponse"/>
  </wsdl:message>

  <wsdl:portType name="UserPortType">
    <wsdl:operation name="GetUser">
      <wsdl:input message="tns:GetUserInput"/>
      <wsdl:output message="tns:GetUserOutput"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:service name="UserService">
    <wsdl:port name="UserPort" binding="tns:UserBinding">
      <soap:address location="https://example.com/services/UserService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

変換後の OpenAPI 3.0

openapi: 3.0.3
info:
  title: UserService API
  description: WSDL から変換した UserService の REST API
  version: 1.0.0

servers:
  - url: https://example.com/api

paths:
  /users/{userId}:
    get:
      operationId: getUser
      summary: ユーザー情報の取得
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: ユーザーが見つからない

components:
  schemas:
    User:
      type: object
      required:
        - id
        - name
        - email
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
        department:
          type: string
          nullable: true

変換時の設計判断

手動変換では、いくつかの設計判断が必要です。

1. SOAP オペレーションから HTTP メソッドへの対応:

SOAP オペレーション名のパターン推奨 HTTP メソッド
Get*Find*Search*GET
Create*Add*Insert*POST
Update*Modify*Set*PUT / PATCH
Delete*Remove*DELETE

2. XSD 型から JSON Schema 型への変換:

# XSD → JSON Schema の型マッピング
xsd:string    → type: string
xsd:int       → type: integer
xsd:long      → type: integer, format: int64
xsd:decimal   → type: number
xsd:boolean   → type: boolean
xsd:dateTime  → type: string, format: date-time
xsd:date      → type: string, format: date
xsd:base64Binary → type: string, format: byte

3. minOccurs / maxOccurs の扱い:

# minOccurs="0" → 必須でない(required に含めない)
# minOccurs="1" → 必須(required に含める)
# maxOccurs="unbounded" → type: array

自動変換ツール

APImatic

APImatic は WSDL を含む多くの API 定義フォーマットの相互変換をサポートするオンラインサービスです。

# APImatic の Transformer API を利用
curl -X POST "https://api.apimatic.io/transformations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@service.wsdl" \
  -F "export_format=OpenApi3Json" \
  -o openapi.json

SoapUI + OpenAPI プラグイン

SoapUI でプロジェクトを作成し、OpenAPI 形式でエクスポートする方法です。

  1. SoapUI で WSDL からプロジェクトを作成
  2. REST Discovery 機能で REST リソースを定義
  3. OpenAPI / Swagger 形式でエクスポート

手動 + テンプレートの組み合わせ

複雑な WSDL の場合、完全自動変換はうまくいかないことが多いです。以下の手順が実用的です。

  1. WSDL のオペレーション一覧を抽出する
  2. OpenAPI のテンプレートを用意する
  3. XSD の型定義を JSON Schema に変換する
  4. パスとオペレーションを手動で設計する
# WSDL からオペレーション名を一覧抽出するワンライナー
curl -s "https://example.com/service?wsdl" | \
  grep -oP 'operation name="\K[^"]+' | sort -u

変換時の注意点

SOAP ヘッダーの扱い

WS-Security などの SOAP ヘッダーは OpenAPI のセキュリティスキームに変換する必要があります。

# WS-Security UsernameToken → HTTP Basic Auth に変換
components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic

security:
  - basicAuth: []

SOAP Fault のマッピング

SOAP Fault はHTTP ステータスコードとエラースキーマに変換します。

responses:
  '400':
    description: リクエストエラー(SOAP Client Fault に対応)
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
  '500':
    description: サーバーエラー(SOAP Server Fault に対応)

複雑な XSD の限界

XSD の choiceanyanyAttribute などの動的な型は JSON Schema で表現が難しく、手動での設計判断が必要です。

変換の手間を省く方法

WSDL から OpenAPI への変換は、一見単純に見えて多くの設計判断と手作業を伴います。特に大規模な WSDL(数十のオペレーション、複雑なネスト型)では、変換作業だけで数日かかることも珍しくありません。

SOAPless は WSDL を自動解析し、REST API エンドポイントを即座に生成します。OpenAPI 定義の手動作成は不要で、WSDL の URL を入力するだけで JSON ベースの REST API がすぐに使えます。SOAP サービスの REST 化を最短で実現したいなら、SOAPless で 30 秒で試してみてください。