Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I've tried using OpenAPI a few times, it's been...lackluster... I probably won't use it again.

Here are my gripes:

1) For me one of the biggest selling points is client code gen (https://github.com/OpenAPITools/openapi-generator). Basically it sucks, or at least it sucks in enough languages to spoil it. The value prop here is define the API once, code gen the client for Ruby, Python and Scala (or insert your languages here). Often there are a half dozen clients for each language, often they are simply broken (the generated code just straight up doesn't compile). Of the ones that do work, you get random PRs accepted that impose a completely different ideological approach to how the client works. It really seems like any PR is accepted with no overarching guidance.

2) JSONSchema is too limited. We use it for a lot of things, but it just makes some things incredibly hard. This is compounded by the seemingly limitless number of version or drafts of the spec. If your goal is interop, which it probably is if you are using JSON, you have to go our and research what the lower common denominator draft spec JSONSchema support is for the various languages you want to use and limit yourself to that (probably draft 4, or draft 7).

On the pros side:

It does make pretty docs - kinda wish it would just focus on this and in the process not be as strict, I think it would be a better project.



I find it odd that you've struggled so much with generating API clients. I've generated C# and TypeScript (Angular's HttpClient and React Query) clients for my API and never had any issues with them. With that being said, I didn't use OpenAPI's Java-based code generators and rather used ones made by third-party developers such as NSwag[0] and openapi-codegen[1].

[0]: https://github.com/RicoSuter/NSwag

[1]: https://github.com/fabien0102/openapi-codegen


You said it yourself — the “official” generator is awful and very hard to modify or extend (well, you didn’t say that, but I’m saying it) and while there are many alternatives, they’re not always easy to find. I had some success with swagger-typescript-api[1], but eventually got tired of it and wrote my own generator. Despite looking around quite a bit at what’s available, I never heard of openapi-codegen, which looks quite good.

I think it’s a pretty big problem for many devs that so many of the options are mediocre and they’re quite difficult to evaluate unless you have a lot of experience, and even then it takes a lot of time.

[1]: https://github.com/acacode/swagger-typescript-api


Technically, there isn't an "official" OpenAPI 3.x tool of any sort. SmartBear/Swagger is no more official than any other vendor with 3.0+ (obviously it's different for the versions named "Swagger"!). I am working on an official parser/linter (oascomply) on a contract for the OpenAPI Initiative to set a baseline to help tool developers implement consistent support for the spec. However, this is more about the parts of OAS outside of the Schema Object.


Nswag leaves much to be desired. I deployed an OpenAPI server and the initial deployment partners using nswag begged us to change the API to suit an issue that was reported and nswag hadn't fixed in years. I respectfully told them to pound sand and deal with it manually or better yet be a good citizen on the ecosystem that they are using for free and contribute a patch. Last I checked they were still manually patching their codegen on each deploy. /Shrug

Nswag has important issues that are many years old still in their backlog.

1.6k issues, oldest unresolved 7 years old:

https://github.com/RicoSuter/NSwag/issues?q=is%3Aissue+is%3A...


I've been using redux toolkit's OpenAPI code generator for a side project and it's been pretty good. The documentation is a bit lacking and it could certainly use more work to make names more customizable. The generated code comes out looking very much machine generated. But I love that RTKQuery (redux toolkit query) has client side caching so that if I use a query param that was already used before, it will remember and just serve from the local cache.

But it's been nice being able to make a backend change, run the code generator, and then be able to use whatever API in react. I hope this type of stuff gets developed more!

[0] - https://github.com/reduxjs/redux-toolkit/tree/master/package...


I've had the same experience and gripes as the comment op, but RTKquery is one of the better experiences I've had with OpenApi based tooling.

But ya... JSONschema is confusing and doesn't really support type composition the way you think it would.

If your API model is simple, then you'll probably have decent experience with clients... But if you need "allOf/anyOf/oneOf" and to restrict "additionalProps", you're probably going to have a rough time...


Yup. JSON Schema is a constraint system, not a data definition system. https://modern-json-schema.com/json-schema-is-a-constraint-s...


This. I've found you can get a long way with NSwag, and the barrier to entry is low. I've got a post that walks through how to get a TypeScript and a C# client generated.

https://johnnyreilly.com/generate-typescript-and-csharp-clie...


I'm working on a company https://speakeasyapi.dev/ with the goal of helping companies in this ecosystem get great production quality client sdks, terraform providers, cli(s) and all the developer surfaces you may want supported for our API. We also manage the spec and publishing workflow for you so all you have to do is build your API and we'll do the rest.

Feel free to email me at sagar@speakeasyapi.dev or join our slack (https://join.slack.com/t/speakeasy-dev/shared_invite/zt-1cwb...) . We're in open beta and working with a few great companies already and we'd be happy for you to try out the platform for free!


Created some accounts for advertising? Accounts created some hours ago and just praising you endlessly…..


The original comment and every reply reads like it was copied straight from a marketing brief. This is everyone's reminder that Hacknernews is not immune to astroturfing, and it's often done much more subtly.


Definitely check out Speakeasy— we've been using them and the experience + team are fantastic


We at Airbyte are happy users of the speakeasy platform. The CLI generator is easy to get started with and generate nice api clients that are constantly getting better. Their api developer platform does a great job of managing new client builds and deploys to the package repositories as well. Super please with the experience so far.


What's the thought process behind the product with API Keys? Why do you build those for your end user, and what's the goal of someone using that. Unless I'm misinterpreting.


+1 to Speakeasy ~ Our end-users love to use the SDKs that are automatically generated through Speakeasy, based off our API.


I've been working with Speakeasy for a couple of month now to produce client libraries for our customers to use. They've finally made an OAS-based code generator that's great. In fact, it's getting even better with useful functionality being released on an almost biweekly basis. I would strongly recommend Sagar and the Speakeasy team to anyone looking to support high quality client libraries for your customers.


I'm one of the builders of an open source project (https://buildwithfern.com/docs) to improve API codegen. We built Fern as an alternative to OpenAPI, but of course we're fully compatible with it.

The generators are open source: https://github.com/fern-api/fern

We rewrote the code generators from scratch in the language that they generate code in (e.g., the python generator is written in python). We shied away from templating - it's easier but the generated code feels less human.

Want to talk client library codegen? Join the Fern Discord: https://discord.com/invite/JkkXumPzcG


I think it's worth pointing out that a lot (most?) of Fern's complaints against OpenAPI are really complaints against JSON Schema. There have been talks before about allowing other schema systems in OpenAPI - I wouldn't be incredibly surprised to see such things come up for Moonwalk. JSON Schema is not not a type definition system https://modern-json-schema.com/json-schema-is-a-constraint-s....

It's also worth noting that most JSON Schema replacements I've seen that prioritize code generation are far less powerful in terms of runtime validation (I have not examined Fern's proposal in detail, so I do not know if this is true for them).

The ideal system, to me (speaking as the most prolific contributor to JSON Schema drafts-07 through 2020-12), would have clearly defined code generation and runtime validation features that did not get in each other's way. Keywords like "anyOf" and "not" are very useful for runtime validation but should be excluded from type definition / code generation semantics.

This would also help balance the needs of strongly typed languages vs dynamically typed languages. Most JSON Schema replacements-for-code-generation I've seen discard tons of functionality that is immensely useful for other JSON Schema use cases (again, I have not deeply examined Fern).


Just wanted to chime in and say we are a big fan of Fern! It makes developing our APIs 10x easier as we get full end-to-end type safety and code completion, but the really great part is we get idiomatic client and server SDKs as well as OpenAPI output that we use to autogen documentation. Our small team of two engineers are able to ship multiple client facing SDKs because we are built on Fern!


Speed of development on these guys is huge, and have enjoyed using their SDKs. Community is getting involved in building things like auto-retry with backoff and other pretty helpful features in SDKs. Big fan of these guys!


I think that’s what most people are using it for, but having a single expressive (debatable) language to describe the contract an api offers has soo much potential.

GraphQL promised us apis that we can trust - since both the client and the server were implemented with the same schema, you would know for sure which requests the api would respond to and how, if it tried to do something outside of the schema, the server lib itself would through a 500 error. This allowed you to generate lean, typesafe clients.

OpenAPI kinda allows you to do that but for any other http api - I’ve written some code to use the schema as a “source of truth” for the server code as well, proving at compile time that the code will do the correct requests and responses for all the endpoints, paths and methods. So if you are reading the schema, you know for sure that the api is going to return this, and any change has to start from modifying the api.

And in turn this allows a “contract first” dev where all parties agree on the api change first, and then go to implement their changes, using the schema as an actual contract.

Combine this with languages with expressive type systems, and it allows you a style of coding thats quite nice - “if it compiles it is guaranteed to be correct”. Now of course this does not catch all bugs, but kinda confines them to mostly business logic errors, and frees you from needing to write tons of manual unit tests for every request.

Oh as a bonus it can be used for runtime request validation as well, which allows you to have types generated for those as well, for the client _and_ the server! Makes changes in the api a lot more predictable.

Client / server code generation can also be implemented as just type generation with no actual code being created, sidestepping a lot of complaints about code generators.

I did package it up as OS https://github.com/ovotech/laminar but no longer have access to maintain it as I no longer work there unfortunately.


> "contract first” dev

Just wanted say that this is very cool and I find it hard to understand why this is not already the norm in 2023. I've done something quite similar in a proprietary project (I called it "spec-driven development" in reference to "test-driven development").

I would first start by writing the OpenAPI spec and response model JSON schema. I could then write the frontend code, for example, as the API it called on the server was now defined. Only as the last step I would actually integrate the API to real data - this was especially nice as the customer in this particular project was taking their time to deliver the integration points.

All the time during development the API conformity was being verified automatically. It saved me from writing a bunch of boilerplate tests at least.


The reason why no one does “contract or spec driven development” is that in most real life cases the spec is not known in advance, and it’s very very hard to get the spec right before starting to write a single line of code.

It’s often much more practical to integrate early and then iterate on the implementation and the spec at the same time until reaching a stable point.


thing is - with this setup the spec is the code you iterate it as you would your implementation - it just makes sure that the its guaranteed to be correct.

What I’ve seen so often (and why I implemented this) was that the spec will be written, found insufficient, and the code updated, leaving the spec out of date.

Having to write the spec first allows you to actually iterate on it before implementing the code, with all the server / test client generators. So the frontend team can start working on its end before the backend even implements anything, as most of its test would be done against mocks / fake data generators.

Even better, since the spec is a source of truth for soo many things - validation, client test requests, server test responses, docs, as well as the paths / endpoints in both client and server implementation, it saves an enormous amount of time and communication energy to have it be implemented in one place.


FWIW, there are a few companies cropping up now doing better codegen for client libraries. I'm starting one of them: https://stainlessapi.com

Unfortunately we don't yet have a "try now" button, and our codegen is still closed-source, but you can see some of the libraries we've generated for companies like Modern Treasury and sign up for the waitlist on our homepage.

Always happy to chat codegen over email etc.


CTO of Modern Treasury here. We're very happy with the quality of the client libraries being generated by Stainless. It also integrates nicely into our workflow, we've got the releases almost fully automated whenever new API routes are added or changed.


I'm looking for a codegen tool for client SDKs for my product, would love to use your product. My email is in my profile, if you want to chat.


Sad to see it isn't just me. I had very real vibes of "surely I'm holding this wrong" in my building an OpenAPI file. And you didn't even mention tools to help deploy, just to help make a client.

To add my difficulty, the document generation inside Sphinx was less than up to date. Such that I didn't even get the pretty docs.


The Java generator is pretty good, many big companies are using it for generating both client and server code, I'm especially happy with the Java Spring Boot generator, I've been using it for both reactive and 'standard' code generation.


I am using the 'spring' generator and it works fine. Just fine. Could be better if it would buse more Spring features.

It saves hours and hours of development time. And the ability to regenerate the whole application on spec changes is amazing.


I'm sorry, but you have completely misunderstood the purpose of Open API.

It is not a specification to define your business logic classes and objects -- either client or server side. Its goal is to define the interface of an API, and to provide a single source of truth that requests and responses can be validated against. It contains everything you need to know to make requests to an API; code generation is nice to have (and I use it myself, but mainly on the server side, for routing and validation), but not something required or expected from OpenAPI

For what it's worth, my personal preferred workflow to build an API is as follows:

1. Build the OpenAPI spec first. A smaller spec could easily be done by hand, but I prefer using a design tool like Stoplight [0]; it has the best Web-based OpenAPI (and JSON Schema) editor I have encountered, and integrates with git nearly flawlessly.

2. Use an automated tool to generate the API code implementation. Again, a static generation tool such as datamodel-code-generator [1] (which generates Pydantic models) would suffice, but for Python I prefer the dynamic request routing and validation provided by pyapi-server [2].

3. Finally, I use automated testing tools such as schemathesis [3] to test the implementation against the specification.

[0] https://stoplight.io/

[1] https://koxudaxi.github.io/datamodel-code-generator/

[2] https://pyapi-server.readthedocs.io

[3] https://schemathesis.readthedocs.io


To your first point - you may think it detracts from perceived value, but you can just write your own code generator for openapi - it's not that hard, and you'll probably end up with a higher quality client that more fits your preferred pattern better.

This is still a win because you can still generate all your clients in sync with your API spec rather than doing all that manually.


> For me one of the biggest selling points is client code gen. Basically it sucks

I agree that the official codegen is not that great. One of my former colleagues started guardrail[0] to offer better client -- and server -- codegen in Scala for a few different http/rest frameworks. Later, I added support for Java and some Java frameworks. (I haven't worked on the project in over a year, but from what I understand, it's still moving forward.)

Obviously that's a fairly limited set of languages and frameworks compared to what the official generators offer, and there are some OpenAPI features that it doesn't support, but guardrail is a good alternative if you're a Java or Scala developer.

> JSONSchema is too limited

I've run into some of the problems you've described, which can be a big bummer. For new APIs I'd designed, I took the approach of designing the API in a way that I knew I could express in OpenAPI without too much trouble, using only the features I knew guardrail supported well (or features I knew I could add support for without too much trouble). It's not really the ideal way to design an API, but after years of that sort of work, I realized one of the worst parts of building APIs is the tedious and error-prone process of building server routes or a client for it, and I wanted to optimize away as much of that as possible.

Ultimately my view is that if you are writing API clients and servers by hand, you're doing it wrong. Even if you end up writing your own bespoke API definition format and your own code generators, that's still better than doing it manually. Obviously, if something like OpenAPI meets your needs, that's great. And even if you don't like the output of the existing code generators, you can still write your own; there are a bunch of parser libraries for the format that will make things a lot easier, and it really isn't that difficult to do, especially if you pare your feature support down to the specifics of what you need.

[0] https://guardrail.dev


I think OpenAPI needs to step up its game with its code generators, because that too has been an issue for me; I've seen a few issues pop up over time.

It's only useful for generating types; most generators' APIs are stubs at best, which means it's pretty much useless for evolving API specifications.

JSON has its limitations, in that its type system is different enough from other languages that back-end generated code often feels awkward.

I think that the foundation should take ownership of the generators and come up with a testing, validation & certification system. Have them write a standardized test suite that can validate a generated client, making sure there's a checklist of features (e.g. more advanced constructs like `oneOf` with a discriminator, enums, things like that).

And they should reduce the number of generators. Have one lead generator for types, then maybe a number of variants depending on what client the user wants to use. But those could be options / flags on the generator.

Of course, taking a step back, maybe OpenAPI and by extension REST/JSON is a flawed premise to begin with; comparing it with e.g. grpc or graphql, those two are fully integrated systems, where the spec and protocol and implementation are much more tightly bound. The lack of tight bounds (or strict standards for that matter) is an issue with REST/JSON/OpenAPI.


I agree that codegen + docs is actually where most of the value is. The problem I think is in the design. Having an intermediate spec makes all the downstream tooling for codegen + docs need to handle all the complexity. Any information lost (because the spec is in sufficient for whatever use case), you end up with a worst of both worlds situation, your code or docs gen tooling is less direct to use, and now is missing context.

Another way of handling this is getting the server your are interacting with to be able to generate the code directly based on their own internal knowledge of how the APIs are put together. This puts more onus on the library creators to support languages etc, but provides a much better experience and better chance things will 'just work' as there are just less moving parts.

ServiceStack is a .NET library that does this with 'Add ServiceStack Reference'[0] which enables a direct generation of Request and Response DTOs with the APIs for the specific server you are integrating with. IDE integration is straight forward since pulling the generated code is just another web service call. Additional language generation are integrated directly. It had trade offs but I'm yet to see a better dev experience.

[0] https://servicestack.net/add-servicestack-reference

(Disclaimer I work for ServiceStack).


I find the code gen less valuable than having a machine-readable spec that I can test against.


It's always nice to read and know I am not an opinionated asshole, and other people share the misery. I admit I've been duped using OpenAPI. Generating the schema via FastAPI and Nest.js works pretty well. But like you we have been sorely disappointment by the codegen.

Anyone care to suggest alternatives though, assuming we want to call from node to python? I actually believe that having api packages with types is one of the only things startups should take from the enterprise world. I thought about GRPC, I had good experience with it as a developer, but the previous company had a team of people dedicated just to help with the tooling around GRPC and Protobufs.

So I picked OpenAPI, figuring simple is better, and plaintext over http is simpler. and currently I do believe it's better than nothing, but not by much. I am actually in the process of trying to write my own codegen and seeing how far I can get with it.

are protobuf's with GRPC really the way to go nowadays? should a startup of 20 developers just give up and document api in some shared knowledge base and that's it?


NSwag does a wonderful job of generating TypeScript clients from OpenAPI specs. Definitely give it a shot before killing your current setup.

https://github.com/RicoSuter/NSwag (It sucks in any OpenAPI yml, not just ones from Swashbuckle/C#)


@sthuck I'm working on an alternative in this space called Fern. Like gRPC, you define your schema and use it to generate client libraries + server code. Fern integrates with FastAPI/Express/Spring and generates clients in Python, Typescript, and Java.

Checkout out this demo: https://www.loom.com/share/42de542022de4e55a1349383c7a465eb. Feel free to join our discord as well: https://discord.com/invite/JkkXumPzcG.


Yeah I had this experience too. I figured at least there'd be static checking that would at least make sure we aren't going off spec but there isn't really. So you just have a spec that slowly becomes out of sync with the code until it's basically useless. Just seems like double work for almost no benefit.


It depends on the tools you use. You can use tester proxies that validate all requests and responses to the specs, or you can do server code gen (with interfaces/Subclasses for example in Java) so you are forced to adhere to the specs.


I actually got the OpenAPI docgen magic to work 100% all the way into Azure API Management Service such that our branded portal's docs were being updated based upon code comments each time upon merge. It really is something to marvel at. It actually worked.

That said, I didn't like the amount of moving pieces, annotation soup in code, etc. I got rid of all of it. Instead of relying on a fancy developer web portal with automagically updating docs, I am maintaining demo integration projects in repositories our vendors will have access to. I feel like this will break a hell of a lot less over time and would be more flexible with regard to human factors. Troubleshooting OpenAPI tooling is not something I want myself or my team worrying about right now.


Good to know. I'd like to learn about the process you had set up and the number of moving pieces it required. Have you written about this process? Can I read about it somewhere?


1) hits home. The lack of a proper AST, "logicless" Mustache templates for code generation, lack of tests,... Also, OpenAPI seems to allow features in the language before at least a handfull of first class code generators have support for that feature, just because one generator supports it. And not that the others refuse, they just produce broken code


As for point 1) I fully agree. I'm using it a lot currently due to lack of alternatives, mainly with java. Swagger codegen is the one I've had most success with, but both openapi and swagger codegen shares the same problems.

For internal projects we use grpc which is a breeze to use in comparison.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: