<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Swagger on Chanomic Blog</title>
    <link>https://bombrary.github.io/blog/tags/swagger/</link>
    <description>Recent content in Swagger on Chanomic Blog</description>
    <generator>Hugo</generator>
    <language>ja-jp</language>
    <lastBuildDate>Sun, 26 Apr 2026 07:48:25 +0000</lastBuildDate>
    <atom:link href="https://bombrary.github.io/blog/tags/swagger/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>OpenAPI定義から特定の要素だけ取り出すスクリプト</title>
      <link>https://bombrary.github.io/blog/posts/openapi-extract-python/</link>
      <pubDate>Sun, 26 Apr 2026 15:05:00 +0900</pubDate>
      <guid>https://bombrary.github.io/blog/posts/openapi-extract-python/</guid>
      <description>&lt;h2 id=&#34;前置き&#34;&gt;前置き&lt;/h2&gt;
&lt;p&gt;OpenAPIスキーマからAPIクライアントを作りたい。そういう場合 &lt;a href=&#34;https://github.com/OpenAPITools/openapi-generator&#34;&gt;OpenAPITools/openapi-generator&lt;/a&gt; を使って生成することになるが、スキーマがあまりにもでかすぎると困る。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;yamlだとファイルがでかすぎるとうまく読めない&lt;/li&gt;
&lt;li&gt;Pythonのようなインタプリタ型のクライアントだとモジュールのロードに時間がかかる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一例として、以下のAPIスキーマを見てほしい。以下はネットワーク仮想化製品であるVMware NSX-TのAPIスキーマであるが、&lt;code&gt;nsx_policy_api.yml&lt;/code&gt; を見ると、テキストファイルなのに12MGもある。jsonファイルですら8.6MBである。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.broadcom.com/xapis/nsx-t-data-center-rest-api/latest/x-references/&#34;&gt;NSX-T Data Center REST API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;こういった外部製品のAPIクライアントを作ることを考えたとき、実際には特定のAPIしか叩かないだろう。もしその特定のAPIのスキーマと関連リソースだけを抽出したスキーマを作れば、軽量なAPIクライアントが作成できることが期待される。&lt;/p&gt;
&lt;p&gt;というわけで本記事では、OpenAPIのスキーマから必要なリソースと関連リソースだけを抽出した新しいスキーマを生成するスクリプトを作成する。&lt;/p&gt;
&lt;h2 id=&#34;設計&#34;&gt;設計&lt;/h2&gt;
&lt;p&gt;今回の目的は「特定のAPIと関連リソースのみを抽出する」ことである。&lt;/p&gt;
&lt;h3 id=&#34;入出力&#34;&gt;入出力&lt;/h3&gt;
&lt;p&gt;そのため、入力と出力はそれぞれ次のようになる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;入力：
&lt;ul&gt;
&lt;li&gt;OpenAPI定義ファイル&lt;/li&gt;
&lt;li&gt;OpenAPI定義ファイルに含まれるAPIパスのリスト&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;出力： OpenAPIスキーマ
&lt;ul&gt;
&lt;li&gt;最もファイルサイズを占めているであろう以下の属性には必要最低限のものが入っている状態となっている
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;paths&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;definitions&lt;/code&gt; (v2.0のみ)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parameters&lt;/code&gt; (v2.0のみ)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;responses&lt;/code&gt; (v2.0のみ)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;components&lt;/code&gt; (v3.0のみ)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OpenAPI には2.0と3.0があるが、特に取り決めない
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/specification/v2/&#34;&gt;OpenAPI Specification - Version 2.0 | Swagger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://swagger.io/specification/v3/&#34;&gt;OpenAPI Specification - Version 3.0 | Swagger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;インターフェース&#34;&gt;インターフェース&lt;/h3&gt;
&lt;p&gt;APIパスのリストは、改行区切りで標準入力から受け取るものとする。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python3 main.py -i input.yml -o output.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;api関連リソースを抽出するロジック&#34;&gt;API関連リソースを抽出するロジック&lt;/h3&gt;
&lt;p&gt;OpenAPIでは、&lt;code&gt;$ref: &amp;quot;#/{attr...}&amp;quot;&lt;/code&gt; のような構文で、別の場所で定義されている要素を参照できる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;/pets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Returns all pets from the system that the user has access to&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;produces&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;application/json&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;responses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;A list of pets.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;$ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;#/definitions/pet&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このような &lt;code&gt;$ref: ...&lt;/code&gt; があるため、完全なAPIスキーマとして抽出するためには、&lt;code&gt;$ref&lt;/code&gt; が参照する先のリソースも漏らさずスキーマとして抽出する必要がある。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
