Wejście (schemat .proto)

Wyjście (OpenAPI YAML)

Co robi to narzędzie

Masz schemat Protocol Buffers i zespół frontendu, partnera albo QA, który chce dokument OpenAPI dla tych samych kształtów — zwykle dlatego, że usługa gRPC jest też wystawiona po HTTP przez coś takiego jak grpc-gateway. Wpięcie protoc-gen-openapiv2 w build to właściwa odpowiedź na produkcji, ale to przesada, gdy potrzebujesz tylko szybkiego speca do podzielenia się albo wrzucenia do Swagger UI. Ten konwerter robi schematową połowę roboty w przeglądarce — wklejasz .proto, kopiujesz YAML i masz prawidłowe components OpenAPI.

Wyjście to minimalny, ale prawidłowy dokument OpenAPI 3.1.0 z pustym paths: {} i jednym wpisem na każdy message lub enum z Protobufa pod components.schemas. Wybieramy konkretnie OpenAPI 3.1, ponieważ jego model danych jest zgodny z JSON Schema 2020-12 — to wersja, w której formaty takie jak int64, date-time i duration są pełnoprawnymi obywatelami i w której $ref może stać obok innych słów kluczowych bez starych obejść z 3.0.

Mapowanie typów idzie zgodnie z mapowaniem JSON proto3: 32-bitowe inty stają się type: integer, format: int32, 64-bitowe — type: string, format: int64 z numerycznym pattern'em (bo liczby JSON powyżej 2^53 tracą precyzję), repeated T staje się tablicą, map<K, V> staje się obiektem z additionalProperties, a nazwy pól pozostają w snake_case, żeby schemat pasował do tego, co serwer naprawdę serializuje. Enumy są emitowane jako type: string z listą enum nazw wartości — tak samo jak w JSON-ie proto3. Konwerter działa w całości w przeglądarce; nic z Twojego schematu nie opuszcza strony.

Jak tego używać

Trzy kroki. Wyjściem jest dokument YAML, który możesz wrzucić do Swagger UI albo dorzucić do istniejącego speca.

1

Wklej swój schemat .proto

Upuść schemat w lewym edytorze. syntax = "proto3"; na górze jest OK, ale opcjonalne. Parser obsługuje zagnieżdżone bloki message, deklaracje enum, oneof, map<K, V> i opcje pól. Instrukcje import pomiędzy plikami są rozpoznawane, ale pomijane — wklej importowane typy inline, jeśli Twoje schematy się wzajemnie odwołują.

Nazwy pól pozostają w wyjściu w snake_case, w zgodzie z domyślnym zachowaniem encodera JSON proto3. Jeśli Twój gateway jest skonfigurowany na nazwy JSON w camelCase, zrób w wyjściu znajdź-zamień albo zmień ustawienie gatewaya.

2

Czytaj wyjście OpenAPI

Po prawej: dokument YAML z openapi: 3.1.0, blokiem info, pustym paths: {} i Twoimi message'ami i enumami pod components.schemas. Odwołania do zagnieżdżonych message'y używają $ref: '#/components/schemas/MessageName' względem nazwy liścia, więc płaskie odwołania działają nawet wtedy, gdy Twój .proto deklaruje typy zagnieżdżone.

3

Podepnij to

Wrzuć plik do instancji Swagger UI albo Redoc, żeby zobaczyć, jak schematy się renderują. Aby zrobić z tego pełny spec, dodaj prawdziwe wpisy paths wskazujące na Twoje trasy grpc-gateway (albo napisz je ręcznie) — zreferencjuj je za pomocą $ref na #/components/schemas/Order i działa.

Kiedy to naprawdę oszczędza czas

Dzielenie się schematem z zespołem frontendu lub partnera

Zespół frontendu konsumuje Twoją usługę gRPC transcodowaną. Poprosili o doc OpenAPI, żeby podpiąć go pod ich generator typów albo przeglądarkę API. Wklej .proto, skopiuj YAML, wyślij. Dostaną schemat w formacie, który ich tooling już rozumie.

Bootstrap speca dla nowego API HTTP transcodowanego

Stawiasz nową usługę, która ma działać i jako gRPC, i jako HTTP przez grpc-gateway z buf. Sekcja components/schemas jest mechaniczna — wygeneruj ją tym narzędziem, a potem ręcznie napisz paths z odpowiednimi szablonami tras. Szybciej niż klepanie wszystkiego od zera.

Trzymanie Swagger UI w synchronizacji ze zmianami w .proto

Twój zespół używa Swagger UI do dokumentacji API czytanej przez ludzi, ale źródło prawdy żyje w plikach .proto. Kolega z backendu dodaje shipping_address do Order; tutaj regenerujesz sekcję schemas, wklejasz ją z powrotem do speca i publikujesz aktualizację dokumentacji.

Sprawdzenie jakości wyjścia z codegenu

Uruchomiłeś protoc-gen-openapiv2 jako część builda i dostałeś plik YAML na 4000 linii. Aby zweryfikować, że konkretny message ma odpowiedni kształt, wklej tutaj tylko ten jeden plik .proto i porównaj. Szybkie odniesienie do tego, jak powinno wyglądać czyste mapowanie OpenAPI 3.1.

Częste pytania

Dlaczego OpenAPI 3.1, a nie 3.0?

OpenAPI 3.1 dopasowuje swój model danych do JSON Schema 2020-12, co oznacza, że formaty takie jak int64, date-time i duration są dobrze zdefiniowane, a $ref można postawić obok innych słów kluczowych bez niewygodnych obejść, których wymagała 3.0. Większość nowoczesnych narzędzi (Redoc, Swagger UI 5, Stoplight, Spectral) bez problemu mówi po 3.1. Jeśli naprawdę potrzebujesz wyjścia 3.0 dla starego toolingu, zmień openapi: 3.1.0 na początku dokumentu — reszta jest na tyle kompatybilna, że zwykle i tak się zwaliduje.

Dlaczego int64 jest wystawiany jako string, a nie liczba?

Liczby JSON to w praktyce double'y IEEE-754 — tracą precyzję powyżej 2^53. Oficjalne mapowanie JSON proto3 mówi, że int64, uint64, fixed64, sfixed64 i sint64 muszą być kodowane jako stringi JSON. Dlatego schemat OpenAPI używa type: string, format: int64, pattern: "^-?[0-9]+$", żeby pasować do tego, co serwer faktycznie wysyła. Jeśli chcesz założyć małe wartości i zamiast tego użyć type: integer, zrób w wyjściu znajdź-zamień.

Dlaczego paths jest puste?

Pliki .proto opisują message i serwisy, a nie trasy HTTP. Transkodowanie HTTP (path, method, query, body) konfiguruje się oddzielnie — zwykle przez adnotacje google.api.http albo opcje grpc-gateway. Nie parsujemy ich, więc zostawiamy paths: {} Tobie do uzupełnienia. Część components/schemas to ta wielokrotnego użytku, mechaniczna połowa — i właśnie ją daje Ci to narzędzie.

Dlaczego nazwy pól są w snake_case?

Bo tak domyślnie koduje JSON proto3. order_id w .proto serializuje się w formacie JSON jako "order_id", chyba że włączysz opcję camelCase (preserve_proto_field_names w niektórych encoderach albo flagę po stronie gatewaya). Trzymanie schematu OpenAPI w snake_case oznacza, że pasuje on do JSON-a, który serwer rzeczywiście wysyła. Jeśli Twój stack robi camelCase, przepuść wyjście przez znajdź-zamień.

Jak są obsługiwane zagnieżdżone message?

Każdy message Protobuf staje się wpisem najwyższego poziomu w components.schemas, indeksowanym po nazwie liścia (Address, nie commerce.v1.Address). Odwołania używają $ref: '#/components/schemas/Address'. Jeśli dwa message mają tę samą nazwę liścia w różnych pakietach, drugi nadpisze pierwszy — rozdziel je na osobne dokumenty albo zmień nazwę w .proto.

Czy rozumie well-known typy z google.protobuf?

Niektóre. google.protobuf.Timestamp renderuje się jako type: string, format: date-time; Duration jako type: string, format: duration; Empty jako pusty obiekt; Any jako ogólny obiekt; Value jako {} (dowolna wartość JSON). Dla pozostałych well-known typów Google'a konwerter aktualnie wystawia $ref do nazwy liścia — możesz albo zdefiniować te schematy samodzielnie, albo zastąpić odwołania właściwym typem prymitywnym.

Powiązane narzędzia

Jeśli pracujesz z Protobufem i OpenAPI/JSON Schema, te dobrze do siebie pasują: