Thanks for sharing your experience! Your post talks a lot about generating clients from OpenAPI specs, which in my opinion (and yours, clearly) is the "right" way to go about it, as opposed to generating OpenAPI from a client's code, which makes the code the source of truth instead of the contract between the server and client. That being said, the nature of OpenAPI and the respective tasks does make it much easier to generate some form of valid OpenAPI documentation from a particular client codebase than it is to generate some form of valid client codebase from any valid OpenAPI. My priorities for my own OpenAPI project, based on complexity mostly, are roughly:
- Finish my implementation of the spec
- Provide hooks for generating OpenAPI from Swift,
- Provide hooks for generating Swift from OpenAPI
Of these three, I am about 90% there on (1) and I've already done quite a bit of preliminary work on (2). I am of course aware of efforts like those described in the other OpenAPI thread that provide (3) via existing tooling, which I think is great, but does not particularly demotivate me from working towards 100% swift implementations.
I'm also specifically enthusiastic about using formal API descriptions to avoid hand-writing API interface code [...] But in practice it's hard [...] because a broader range of things can be expressed in OpenAPI.
This is definitely difficult, and in particular with OpenAPI, as you point out as well. Not only can OpenAPI represent a broad range of things, but it represents those things in a relatively flexible way. For example, realistically any given endpoint has 1 set of possible parameters it accepts and yet OpenAPI lets you define those parameters in multiple locations. The flexibility makes the spec more usable as an author, but more cumbersome as a consumer.
One of my express goals for my own OpenAPI project is to give access to "canonical" representations of OpenAPI components (i.e. a new endpoint structure that would be guaranteed to fully encapsulate the spec for a single endpoint). This will come after I have finished a full representation of the spec (which I am nearing completion of). At that point, it at least becomes easier to write a tool that does whatever with the various OpenAPI components.
you might find it helpful to find a way to automatically compare OpenAPI representation against a JSON Schema of the spec
To my knowledge, the reason there is not an official JSON Schema representation of the spec is that JSON Schema cannot properly represent all of the rules in the spec -- I don't have any examples prepared, I've just read this before. Regardless, this may be a moot point for the OpenAPI implementation I have here because I have represented the rules of OpenAPI natively in Swift types so there are very few places where it is even possible to represent invalid OpenAPI using my library; that, combined with
Codable support, means that the act of decoding an OpenAPI document using my library provides the same validation you would be seeking by matching a document against a JSON Schema representation of the spec. That being said, the human-readability of error reporting upon failure to decode in my library is an area for improvement.
generate a Protocol Buffer representation for a Go tool that I wrote
This is really cool! I've not had time to dive into protobuf so it's all a bit foreign to me, but that looks impressive.