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

Cannot create a useable schema #288

Closed
schmurfy opened this issue Jan 24, 2021 · 5 comments · Fixed by #320
Closed

Cannot create a useable schema #288

schmurfy opened this issue Jan 24, 2021 · 5 comments · Fixed by #320

Comments

@schmurfy
Copy link

I am taking the reverse road most usually take by generating openapi3 documentation from a minimal http framework on top of chi, the start was pretty fast and I can generate everything I need for the request path arguments but I am stuck trying to generate a schema for the requestBody of an operation, my best attempt so far is:

type Pet struct {
  Id   string `json:"id"`
  Name string `json:"name"`
}

gen := openapi3gen.NewGenerator()

// bodyField points to `Pet` reflected type
bodySchema, err := gen.GenerateSchemaRef(bodyField.Type)
// error is checked but I removed it for clarity

body := openapi3.NewRequestBody()
body.Content = openapi3.NewContentWithJSONSchema(bodySchema.Value)
bodyRef := &openapi3.RequestBodyRef{
  Value: body,
}

op.RequestBody = bodyRef
swagger.AddOperation(pattern, method, op)

Aside from being really verbose (there may be faster way to do things but that's the best I found for now) this works but generates:

{
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "id": {
            "$ref": "string"
          },
          "name": {
            "$ref": "string"
          }
        },
        "type": "object"
      }
    }
  }
}

this cause the viewers to try and request <my-domain>/string and i am not sure what I missed, from what I understand internal references should start with "#" but I see no way of influencing what ref are generated and I feel my lack of familiarity with openapi3 does not help xD

Any help or pointer in the right direction will be greatly appreciated :)

@fenollp
Copy link
Collaborator

fenollp commented Jan 24, 2021

What's openapi3gen? I'd suggest taking a close look at what it outputs.

When your code doesn't do what you expected, it's simpler to cut it in smaller and smaller parts and to verify what happens v should happen at these boundaries. Start with largeish parts then go finer.

@schmurfy
Copy link
Author

schmurfy commented Jan 24, 2021

I don't get your answer, the only reason I wrote a larger piece of my code is to provide context, the only part I have problem with is the generated schema from my object created by GenerateSchemaRef , the json in the second block, maybe I just don't understand how to use it but there are no real example either.

What I ideally want for the requestBody is (no $refs ):

{
  "content": {
    "application/json": {
      "schema": {
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "type": "object"
      }
    }
  }
}

The comment on package openapi3genitself confirms it is indeed what I want:

// Package openapi3gen generates OpenAPI 3 schemas for Go types.

I want to build an openapi schema for my existing structure Pet
I even did a test by replacing $refs by type in the generated output (as shown in the block above) and it worked fine in rapidoc.

@fenollp
Copy link
Collaborator

fenollp commented Jan 24, 2021

Wow haha I did not realize this package was part of this very repo!
So yeah I'm not familiar with this but looking at the docs I think you should have better luck using NewSchemaRefForValue.
See the tests for example usage (a tip to beginners: always look at the tests):

func TestSimple(t *testing.T) {
type ExampleChild string
type Example struct {
Bool bool `json:"bool"`
Int int `json:"int"`
Int64 int64 `json:"int64"`
Float64 float64 `json:"float64"`
String string `json:"string"`
Bytes []byte `json:"bytes"`
JSON json.RawMessage `json:"json"`
Time time.Time `json:"time"`
Slice []*ExampleChild `json:"slice"`
Map map[string]*ExampleChild `json:"map"`
Struct struct {
X string `json:"x"`
} `json:"struct"`
EmptyStruct struct {
X string
} `json:"structWithoutFields"`
Ptr *ExampleChild `json:"ptr"`
}
schema, refsMap, err := NewSchemaRefForValue(&Example{})
require.NoError(t, err)
require.Len(t, refsMap, 14)
data, err := json.Marshal(schema)
require.NoError(t, err)
require.JSONEq(t, expectedSimple, string(data))
}
const expectedSimple = `
{
"type": "object",
"properties": {
"bool": {
"type": "boolean"
},

@schmurfy
Copy link
Author

I did have a look at NewSchemaRefForValue but failed to use it on first try, I had another look and found my solution.
The key was:

  for ref := range gen.SchemaRefs {
    ref.Ref = ""
  }

After removing the refs it generates what I expected.

This package is nice but finding your way around is not that intuitive especially when I feel like one of the very few to generate schema from code instead of the opposite xD

@fenollp
Copy link
Collaborator

fenollp commented Jan 25, 2021

PRs welcomed. If you can open a PR with your example code as a test or as an example I'll get it merged.

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

Successfully merging a pull request may close this issue.

2 participants