Generowanie kodu z OpenAPI

PA
  • Rejestracja:ponad 10 lat
  • Ostatnio:16 dni
  • Postów:61
0

Cześć,
czy ktoś z was używa generatora serwera oraz modeli z OpenAPI?
Próbowałem 2 i nie do końca jestem z nich zadowolony:
https://github.com/OpenAPITools/openapi-generator
https://github.com/deepmap/oapi-codegen

Wygenerowane modele są ok, ale mam problem z wygenerowaniem całego boiler plate pod kontrolery.
Zależy mi na tym, by móc pracować z OpenAPI jak z Graphql, czyli móc wygenerować kod, który wyciąga z requestów body, headery, żebym nie musiał tego ręcznie robić.

Jakie są wasze doświadczenia z generowaniem kodu na podstawie specyfikacji OpenAPI?

edytowany 2x, ostatnio: hauleth
no_solution_found
  • Rejestracja:prawie 18 lat
  • Ostatnio:5 dni
3

ja to próbowałem robić i skończyło się tym, że piszę to ręcznie. W Go nie ma dobrego generatora (a przynajmniej takiego, którego znam), a żeby dawał rozsądny kod wynikowy


GG
  • Rejestracja:około 11 lat
  • Ostatnio:około 3 lata
  • Postów:10
1

Możesz powiedzieć na czym polegają problemy z "wygenerowaniem całego boiler plate pod kontrolery "? Używałem https://github.com/deepmap/oapi-codegen z echo i wszystko śmigało

ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

Ja pracowałem długo w projekcie komercyjnym z użyciem: https://github.com/go-swagger/go-swagger
Było ok. Oczywiście nie wszystko idealnie, ale i tak wydaje mi się, że sporo czasu to zaoszczędzało i do tego jeszcze mieliśmy dokumentacje od razu.
Dużym minusem wspomnianej paczki jest brak obsługi openapi v3, więc w wielu przypadkach dyskwalifikuje jej użycie.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0

Pytanie do społeczności - nie znam tej technologii, więc może czegoś nie łapię, ale może ktoś mi wytłumaczyć czemu się nie da w tym przypadku zbudować po prostu odpowiedniej abstrakcji na to? Bo jeśli coś jest tak nieistotne, że aż musimy to generować, to to wydawać by się mogło jest idealnym kandydatem na to żeby to gdzieś schować, i potem po prostu użyć w kodzie?

Chyba że palnąłem teraz totalną bzdurę, bo się nie znam.

ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

@Riddle: Nie do końca rozumiem pytanie, ale jeśli dobrze zgaduję, to pytasz o co tu chodzi,

idea jest taka, że tworzę serwis, który ma jakieś endpointy. Każdy endpoint ma zdefiniowany payload, który trzeba mu wysłać i też to co ten endpoint zwraca.
No to siadam do kodu i muszę stworzyć struktury, które reprezentują ten payload i zwrotkę. Serwis zazwyczaj mogą mieć sporo takich endpointów, więc miałbym sporo pisania kodu, który w sumie mógłbym wygenerować. Do tego dochodzi jeszcze trochę więcej rzeczy, które można wygenerować np. niektóre pola muszę spełniać jakieś warunki tzn. może coś np. musi być emailem, może coś musi być liczbą a nie stringiem etc. Bez generowania niczego bym musiał siedzieć i pisać ten kod, ale po co jeśli jest jakieś narzędzie, które może go wygnerować. No i do tego wszystkiego, dobrze, żeby serwis miał dokumentację, więc ja lubię podchodzić do tego w ten sposób, że pisze najpierw dokumentację w openapi, bo i tak jej potrzebuję. Jak przejdę całą tą przygodę w ten sposób, to kończę z działającym kodem i odpowiednią dokumentacją co wg mnie jest super. Oczywiście im bardziej niestandardowe endpointy, to tym trudniej do tego w ten sposób podejść.

Do tego wszystkiego można dodać, że takie podejście można z powodzeniem stosować w innych językach technologiach, nie jest to tylko specyficzne dla Go.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
Ąowski napisał(a):

@Riddle: Nie do końca rozumiem pytanie, ale jeśli dobrze zgaduję, to pytasz o co tu chodzi,

idea jest taka, że tworzę serwis, który ma jakieś endpointy. Każdy endpoint ma zdefiniowany payload, który trzeba mu wysłać i też to co ten endpoint zwraca.
No to siadam do kodu i muszę stworzyć struktury, które reprezentują ten payload i zwrotkę. Serwis zazwyczaj mogą mieć sporo takich endpointów, więc miałbym sporo pisania kodu, który w sumie mógłbym wygenerować. Do tego dochodzi jeszcze trochę więcej rzeczy, które można wygenerować np. niektóre pola muszę spełniać jakieś warunki tzn. może coś np. musi być emailem, może coś musi być liczbą a nie stringiem etc. Bez generowania niczego bym musiał siedzieć i pisać ten kod, ale po co jeśli jest jakieś narzędzie, które może go wygnerować. No i do tego wszystkiego, dobrze, żeby serwis miał dokumentację, więc ja lubię podchodzić do tego w ten sposób, że pisze najpierw dokumentację w openapi, bo i tak jej potrzebuję. Jak przejdę całą tą przygodę w ten sposób, to kończę z działającym kodem i odpowiednią dokumentacją co wg mnie jest super. Oczywiście im bardziej niestandardowe endpointy, to tym trudniej do tego w ten sposób podejść.

:|

No to to jeszcze bardziej brzmi jak na to się powinno nałożyć abstrakcję, zamiast "generować" cokolwiek.

No to siadam do kodu i muszę stworzyć struktury, które reprezentują ten payload i zwrotkę - no widocznie nie musisz, skoro one są na tyle powtarzalne, przewidywalne i samopodobne że jakiś genrator jest w stanie je wytworzyć.

Serwis zazwyczaj mogą mieć sporo takich endpointów, więc miałbym sporo pisania kodu, który w sumie mógłbym wygenerować. a to z kolei żywcem brzmi jak nieumiejętność reużywania kodu. Zamiast tego ja bym powiedział "Serwis wymaga obsługiwać wiele różnych pathów, ale skoro da się je przewidzieć, to można je schować w abtrakcji, która oszczędzi mi sporo pisania kodu".

Powinna powstać warstwa abstrakcji w której musisz podać tylko te rzeczy które wsadzasz do tego generatora (np to czy pole jest emailem czy nie), i to po prostu działa - bez żadnych struktur. Taka warstwa abstrakcji powinna się zapiąć pod kontrolery, które powinny własnie ją obsługiwać zamiast te wasze struktury. Wtedy nie musiałbyś nic generować, a kod byłby krótszy i prostszy.

edytowany 4x, ostatnio: Riddle
ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

skoro one są na tyle powtarzalne, przewidywalne i samopodobne że jakiś genrator jest w stanie je wytworzyć

Ale one mogą być zupełnie różne od siebie. To, że generator może je wytworzyć/wygenerować, to nie znaczy, że muszą być podobne do siebie. Nie wiem czy do końca rozumiem w którą stronę zmierzasz.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
Ąowski napisał(a):

skoro one są na tyle powtarzalne, przewidywalne i samopodobne że jakiś genrator jest w stanie je wytworzyć

Ale one mogą być zupełnie różne od siebie. To, że generator może je wytworzyć/wygenerować, to nie znaczy, że muszą być podobne do siebie. Nie wiem czy do końca rozumiem w którą stronę zmierzasz.

Masz jakiś input, wsadzasz go w generator, generator wypluwa Ci jakiś kod i ten kod wsadzasz do projektu, i używasz w swoim kodzie.

Pytanie po co? Czemu Twój kod nie może używać tego inputa który wsadzasz do generatora? I pominąć ten generator całkowicie. To wygląda jak miejsce w którym można dodać ładną abstrakcję, i ułatwić sobie życie.

edytowany 1x, ostatnio: Riddle
ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

Inputem w tym przypadku jest dokumnetacja/specyfikacja openAPI, czyli w zasadzie plik YAML/JSON.
Nie zrobię tak, bo Go nie rozumie/nie parsuje/nie kompiluje inputu samego w sobie.

edytowany 1x, ostatnio: Ąowski
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
Ąowski napisał(a):

Inputem w tym przypadku jest dokumnetacja/specyfikacja openAPI, czyli w zasadzie plik YAML/JSON.
Nie zrobię tak, bo Go nie rozumie/nie parsuje/nie kompiluje inputu samego w sobie.

To jeszcze bardziej potwierdza, że tak na prawdę tutaj powinna być abstrakcja - a zamiast tego się dzieje jakieś nie wiadomo co, i wrzucanie niepotrzebnie wygenerowanego kodu do projektu.

Czemu nie zrobić dictionary key->value, albo drzewo faktycznych inputów (nazwy pół, to czy jest mailem czy nie, dodatkowe informacje), i niech z tej kolekcji się generuje Twoje openAPI i niech z tego korzystają kontrolery i endpointy.

Wtedy dodanie nowego feature'a sprowadzałoby się do zadeklarowania takiego słownika, i reszta by się zrobiła "sama".

edytowany 1x, ostatnio: Riddle
ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

Czyli sugerujesz, że można byłoby napisać kawałek kodu, który po prostu ten input by rozumiał? Albo trzymać go w postaci słownika/dictionary?
A no właśnie taki YAML/JSON zgodny ze specyfikacją openAPI już jest tym słownikiem, więc słownik już mamy.

A ten generator właśnie korzysta z tego słownika.

Rozumiem, że ten wygenerowany kod Ci się nie podoba. No dałoby się napisać taki kawałek kodu, który na podstawie tego słownika byłby wstanie wszystko ogarnąć bez generowania, ale wydaje mi się, że w Go, żeby to zadziałało, to skończyłoby się z masą generyków/interface{} itd. (przez to, że w Go jest silne typowanie). Dodam jeszcze, że interface{} jest czymś w rodzaju mixed z PHP, a generyki zostały nie tak dawno do Go wprowadzone, są względnie nowe i nie radzą sobie jeszcze w każdej sytuacji.

Bardzo wątpię, żeby ten kod naprawdę był prostszy i krótszy, ale oczywiście mogę się mylić.

edytowany 1x, ostatnio: Ąowski
markone_dev
  • Rejestracja:około 3 lata
  • Ostatnio:około 6 godzin
  • Postów:811
0

Używałem takich generatorów w aplikacjach opartych o Angular i ASP.NET Core i zawsze wygenerowany kod nie był idealny więc nie wiem czy znajdziesz taki który cię zadowoli. One tak jak napisałeś zwykle generują jakiś domyślny boiler plate, który i tak potem trzeba dostosować pod wymagania w projekcie - bezpośrednie referencje, zahardkodowane url-e, itd.


Programujący korpo architekt chmurowy.
Udzielam konsultacji i szkoleń w obszarze szeroko pojętego cloud computingu (Azure, AWS) i architektury systemów IT. Dla firm i prywatnie.
DevOps to proces nie stanowisko.
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0
Ąowski napisał(a):

Czyli sugerujesz, że można byłoby napisać kawałek kodu, który po prostu ten input by rozumiał? Albo trzymać go w postaci słownika/dictionary?
A no właśnie taki YAML/JSON zgodny ze specyfikacją openAPI już jest tym słownikiem, więc słownik już mamy.

Ale to musi być słownik wyrażony w języku programowania (więc np HashMap w javie, tablica asocjacyjna w PHP). Nie wiem jaki jest w GO.

Rozumiem, że ten wygenerowany kod Ci się nie podoba. No dałoby się napisać taki kawałek kodu, który na podstawie tego słownika byłby wstanie wszystko ogarnąć bez generowania, ale wydaje mi się, że w Go, żeby to zadziałało, to skończyłoby się z masą generyków/interface{} itd. (przez to, że w Go jest silne typowanie).

Jeśli napiszesz to w głupi sposób, to pewnie tak. Ale w zupełności da się to napisać prosto.

Bardzo wątpię, żeby ten kod naprawdę był prostszy i krótszy, ale oczywiście mogę się mylić.

To pokaż przykład Twojego OpenAPI oraz wszystkie pliki które ten generator Ci generuje, to Ci pokażę.

ĄO
  • Rejestracja:około 12 lat
  • Ostatnio:około 5 godzin
  • Postów:236
0

To pokaż przykład Twojego OpenAPI oraz wszystkie pliki które ten generator Ci generuje, to Ci pokażę.

Niestety nie mogę się tym podzielić, ponieważ należy to do firmy w której pracuje, ale nie powinieneś mieć problemu ze znalezieniem przykładu gdzieś tutaj: https://github.com/go-swagger/go-swagger

Ale to musi być słownik wyrażony w języku programowania (więc np HashMap w javie, tablica asocjacyjna w PHP). Nie wiem jaki jest w GO.

W go jest mapa i zajęło by to bardzo mało linijek kodu, żeby wczytać takiego JSONa/YAMLa do tej mapy w Go, więc można powiedzieć, że nie musimy się tym zbytnio przejmować, że to nie jest wprost w kodzie zdefiniowane.

Jeśli napiszesz to w głupi sposób, to pewnie tak. Ale w zupełności da się to napisać prosto.

Myślę, że to dość odważne stwierdzenie, ale chętnie bym to zobaczył. Myślę, że jak napisałbyś to w zupełności prosto i fajnie, to bardzo szybko zostałbyś milionerem także nie wahaj się ani chwili tylko bierz się do roboty.

Przychodzi mi tutaj na myśl generowanie kodu dla gRPC. Historia w pewien sposób podobna. Endpointy/metody definiuje się w plikach .proto . Do tego w parze idą odpowiednie narzędzia, które generują kod z tych definicji. Już jest to dość popularne i popularność jeszcze się zwiększa. Opracowane i wspierane przez Google. W każdej pracy w której pracowałem w GoLang przez ostatnie 4 lata się z tym spotykałem. Więcej tutaj: https://grpc.io/

edytowany 2x, ostatnio: Ąowski
99xmarcin
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:2420
0

Swagger/OpenApi opiera się na szablonach. Jeżeli nie ma szablonu który Ci odpowiada to nie jest żadnym problemem stworzyć w tydzień zestaw szablonów skrojony pod waszą aplikację. Będzie to dodatkowy koszt przy utrzymaniu programu ale przy wielu endpointach może okazać się dobrą inwestycją.

Generalnie w OpenApi wybiera się język i framework docelowy, więc wszystko zależy od tego jakiego frameworka web'owego w Go użyjesz. Na pewno jest coś co pozwoli zdeserializować JSON do konkretnego obiektu w Go.


Holy sh*t, with every month serenityos.org gets better & better...
edytowany 1x, ostatnio: 99xmarcin
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)