Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the expected way to load extensions as complex types? #8

Closed
danielgtaylor opened this issue Nov 4, 2022 · 6 comments
Closed
Labels
documentation Improvements or additions to documentation

Comments

@danielgtaylor
Copy link
Contributor

danielgtaylor commented Nov 4, 2022

I have an extension x-cli-config that enables client auto-configuration given an Open API 3 document (think stuff like security set up, additional headers to always send, and an ability to prompt users for information). This configuration object is somewhat complex with a number of nested fields/objects.

It looks like libopenapi loads extensions as interface{} while kin-openapi loaded them as json.RawMessage. You can unmarshal the raw message into your struct fairly easily, but there is no stdlib way to unmarshal from already existing Go maps. For now I'm trying to use mapstructure to do something similar going from interface{} -> my struct, like so:

var config *autoConfig

if err := mapstructure.Decode(model.Extensions["x-cli-config"], &config); err != nil {
  fmt.Fprintf(os.Stderr, "Unable to unmarshal x-cli-config: %v", err)
  return
}

Is this the right way to do it? Is there some other way you expect users of the library to load their extensions? Some kind of way to register an extension with a type before loading might be nice, and then during loading it could instantiate that type, though maybe that's overkill for this library.

Part of danielgtaylor/restish#115.

@daveshanley
Copy link
Member

daveshanley commented Nov 7, 2022

I left this open-ended to see how people would prefer to consume these extensions. This use case has come up in another project as well.

There are two ways we can currently do this. You're already using the first method (which is fine if you already have the dependency in the project), or you can use GoLow() and extract the *yaml.Node object that represents the raw data and serialize that node into a struct using Decode or Encode (https://pkg.go.dev/gopkg.in/yaml.v3#Node.Decode)

I like your idea of 'registering extensions' with a type. It makes a lot of sense. It would be a nice feature to add once the library's core is in place. I'm working on a 'what-changed' feature right now and then validation after that., perhaps this would be a good follow-up feature. mainly because extensions are so crucial for custom development.

@TristanSpeakEasy
Copy link
Contributor

Can I maybe suggest until a feature targeted at extensions is made, that the current options are documented instead?

@daveshanley
Copy link
Member

I'll update the README with a blurb and some examples and add some sample code to the docs.

daveshanley added a commit that referenced this issue Dec 2, 2022
The more in-depth we use extensions, the more likely is is that we need custom extensions. New `UnpackExtensions` function in the high package makes this easy. Low level models have been updated to support feature fully and docs added in README and examples as well.

Signed-off-by: Dave Shanley <dave@quobix.com>
@daveshanley
Copy link
Member

daveshanley commented Dec 2, 2022

Ok, so I went a step further and created the first step toward a register types function. To begin, there is a new UnpackExtensions function available in the high package of data model.

There is an example available:

https://github.com/pb33f/libopenapi#loading-extensions-using-complex-types

It should make working with complex types and extensions much easier and reduce a lot of code. It should work until a more powerful, auto-magic version of this feature can exist, but that's more work than I have time for right now.

The README has been updated, and the docs with working sample code.

Available in v0.3.2

@daveshanley
Copy link
Member

Updated docs are available here:

https://pb33f.io/libopenapi/extensions/

@daveshanley daveshanley added the documentation Improvements or additions to documentation label Oct 5, 2023
@daveshanley
Copy link
Member

Extensions now arrive as *yaml.Node which allows end-users to define what to do with them. libopenapi hands you control to make your own choices.

Closing this as answered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants