Protobuf'tan OpenAPI'ye Dönüştürücü
Bir .proto şeması yapıştır. Mesajların ve enum'ların components.schemas olarak çıktılandığı bir OpenAPI 3.1 YAML dökümanı al — spec'ine yapıştırmaya hazır.
Girdi (.proto şeması)
Çıktı (OpenAPI YAML)
Bu araç ne işe yarar
Elinde bir Protocol Buffers şeması var ve aynı yapıların OpenAPI dökümanını isteyen bir frontend, partner veya QA ekibi var — genelde gRPC servisi grpc-gateway gibi bir şeyle HTTP üzerinde de açıldığı için. Build'ine protoc-gen-openapiv2 kurmak prodüksiyon için doğru cevap, ama paylaşmak veya bir Swagger UI'ya atmak için hızlı bir spec lazım olduğunda fazla iş. Bu dönüştürücü işin şema yarısını tarayıcında halleder — .proto'yu yapıştır, YAML'ı kopyala, geçerli OpenAPI components'ine sahipsin.
Çıktı, boş bir paths: {} ve components.schemas altında her Protobuf mesajı veya enum için bir giriş içeren minimal ama geçerli bir OpenAPI 3.1.0 dökümanıdır. Özellikle OpenAPI 3.1'i seçiyoruz çünkü veri modeli JSON Schema 2020-12 ile hizalı — bu, int64, date-time ve duration gibi formatların birinci sınıf vatandaş olduğu ve $ref'in eski 3.0 yeniden yazma hilelerine ihtiyaç duymadan diğer keyword'lerle yan yana durabildiği sürüm.
Tip eşleme proto3 JSON eşlemesini izler: 32-bit tam sayılar type: integer, format: int32 olur, 64-bit tam sayılar sayısal bir pattern ile type: string, format: int64 olur (çünkü 2^53 üstü JSON sayıları hassasiyet kaybeder), repeated T bir array'e dönüşür, map<K, V> additionalProperties içeren bir nesneye dönüşür ve alan adları snake_case kalır, böylece şema sunucunun gerçekten serialize ettiği şeyle eşleşir. Enum'lar değer adlarının enum listesiyle birlikte type: string olarak çıkar — proto3 JSON'la aynı. Dönüştürücü tamamen tarayıcında çalışır; şemandan hiçbir şey sayfanın dışına çıkmaz.
Nasıl kullanılır
Üç adım. Çıktı, bir Swagger UI'ya atabileceğin veya mevcut bir spec ile birleştirebileceğin bir YAML dökümanıdır.
.proto şemanı yapıştır
Şemayı soldaki editöre bırak. En üstteki syntax = "proto3"; tamamdır ama isteğe bağlı. Parser iç içe message bloklarını, enum bildirimlerini, oneof, map<K, V> ve alan opsiyonlarını idare eder. Dosyalar arası import ifadeleri tanınır ama atlanır — şemaların birbirine referans veriyorsa içeri alınan tipleri inline yapıştır.
Çıktıda alan adları snake_case kalır, bu proto3 JSON encoder varsayılanıyla eşleşir. Gateway'in camelCase JSON adlarına ayarlıysa çıktıda bul-değiştir yap veya gateway ayarını değiştir.
OpenAPI çıktısını oku
Sağda: openapi: 3.1.0, bir info bloğu, boş bir paths: {} ve components.schemas altındaki mesajların ile enum'ların bulunduğu bir YAML dökümanı. İç içe mesaj referansları yaprak adına karşı $ref: '#/components/schemas/MessageName' kullanır, dolayısıyla .proto iç içe tipler bildirse bile düz referanslar çalışır.
Bağla
Şemaların nasıl render edildiğini görmek için dosyayı bir Swagger UI veya Redoc instance'ına bırak. Bunu tam bir spec'e çevirmek için grpc-gateway rotalarını gösteren gerçek paths girişlerini ekle (ya da elle yaz) — onları $ref ile #/components/schemas/Order üzerinde referansla, tamam.
Gerçekten zaman kazandırdığı durumlar
Bir frontend veya partner ekibiyle şema paylaşmak
Bir frontend ekibi gRPC transcode edilmiş servisini tüketiyor. Tip generator'larına veya API explorer'larına takmak için bir OpenAPI dökümanı istediler. .proto'yu yapıştır, YAML'ı kopyala, gönder. Şemayı zaten araçlarının anladığı bir formatta alırlar.
Yeni bir HTTP-transcode API spec'ini başlatmak
Hem gRPC hem de HTTP olarak buf'lı grpc-gateway üzerinden çalışacak yeni bir servis kuruyorsun. components/schemas bölümü mekanik — bu araçla üret, sonra doğru rota şablonlarıyla paths'i elle yaz. Hepsini sıfırdan kurmaktan daha hızlı.
.proto değişiklikleriyle bir Swagger UI'yı senkron tutmak
Ekibin insan-okunabilir API dökümanı için Swagger UI kullanıyor ama doğruluğun kaynağı .proto dosyalarında yaşıyor. Backend'deki bir arkadaşın Order'a shipping_address ekliyor; sen burada schemas bölümünü yeniden üretip spec'e geri yapıştırıyor ve döküman güncellemesini yayınlıyorsun.
Codegen çıktısını sağlık kontrolünden geçirmek
Build'in bir parçası olarak protoc-gen-openapiv2 çalıştırdın ve 4000 satırlık bir YAML dosyası elde ettin. Belirli bir mesajın doğru şekilde olduğunu doğrulamak için sadece o tek .proto dosyasını buraya yapıştır ve karşılaştır. Temiz bir OpenAPI 3.1 eşlemesinin nasıl görünmesi gerektiğine dair hızlı bir referans.
Sık sorulan sorular
Neden OpenAPI 3.0 değil de 3.1?
OpenAPI 3.1 veri modelini JSON Schema 2020-12 ile hizalar; bu da int64, date-time ve duration gibi formatların iyi tanımlandığı ve $ref'i 3.0'ın gerektirdiği garip dolambaçlı çözümler olmadan diğer keyword'lerle yan yana koyabildiğin anlamına gelir. Çoğu modern tool (Redoc, Swagger UI 5, Stoplight, Spectral) 3.1'i sorunsuz konuşur. Eski tooling için gerçekten 3.0 çıktısına ihtiyacın varsa, dökümanın en üstündeki openapi: 3.1.0'ı değiştir — geri kalanı genelde hâlâ doğrulanacak kadar uyumludur.
int64 neden sayı değil string olarak çıkıyor?
JSON sayıları pratikte IEEE-754 double'larıdır — 2^53 üstünde hassasiyet kaybederler. Resmi proto3 JSON eşlemesi int64, uint64, fixed64, sfixed64 ve sint64'ün JSON string'i olarak kodlanmasını söyler. Bu yüzden OpenAPI şeması, sunucunun gerçekten gönderdiğiyle eşleşmek için type: string, format: int64, pattern: "^-?[0-9]+$" kullanır. Küçük değerler varsayıp type: integer kullanmak istiyorsan çıktıda bul-değiştir yap.
paths neden boş?
.proto dosyaları mesajları ve servisleri tanımlar, HTTP rotalarını değil. HTTP transcoding (path, method, query, body) ayrı yapılandırılır — genellikle google.api.http annotation'ları veya grpc-gateway opsiyonları üzerinden. Bunları parse etmiyoruz, bu yüzden paths: {}'i senin doldurman için bırakıyoruz. components/schemas kısmı yeniden kullanılabilir, mekanik yarıdır — bu aracın sana verdiği şey budur.
Alan adları neden snake_case?
Çünkü proto3 JSON varsayılan olarak böyle kodlar. .proto'daki order_id, camelCase opsiyonunu (bazı encoder'lardaki preserve_proto_field_names veya gateway tarafındaki bayrak) açmadıkça JSON wire formatında "order_id" olarak serialize edilir. OpenAPI şemasını snake_case'te tutmak, sunucunun gerçekten gönderdiği JSON'la eşleştiği anlamına gelir. Stack'in camelCase yapıyorsa çıktıyı bir bul-değiştirden geçir.
İç içe mesajlar nasıl ele alınıyor?
Her Protobuf mesajı, yaprak adına göre (commerce.v1.Address değil Address) anahtarlanan ve components.schemas altında üst düzey bir giriş olur. Referanslar $ref: '#/components/schemas/Address' kullanır. Farklı paketlerde aynı yaprak adına sahip iki mesaj varsa, ikincisi birincisinin üzerine yazar — onları ayrı dökümanlara böl ya da .proto'da yeniden adlandır.
google.protobuf well-known type'larını iyi anlıyor mu?
Birkaçını. google.protobuf.Timestamp type: string, format: date-time olarak; Duration type: string, format: duration olarak; Empty boş bir nesne olarak; Any genel bir nesne olarak; Value ise {} olarak (herhangi bir JSON değeri) çıkar. Diğer Google well-known type'ları için dönüştürücü şu anda yaprak adına bir $ref üretir — bu şemaları kendin tanımlayabilir veya referansları doğru ilkel tiple değiştirebilirsin.
İlgili araçlar
Protobuf ve OpenAPI/JSON Schema ile uğraşıyorsan, bunlar iyi bir ikili oluşturuyor: