swaggest / jsonschema-go

JSON Schema mapping for Go
https://pkg.go.dev/github.com/swaggest/jsonschema-go
MIT License
112 stars 14 forks source link

Example tags show problems #53

Closed fjzcxs closed 2 years ago

fjzcxs commented 2 years ago

The following seems to be the correct parsing

type TestStruct struct {
    Time []string `json:"time,omitempty" examples:"[\"Xiao\",\"Dao\"]" example:"Xiao"`
}

func main() {
    reflector := jsonschema.Reflector{}
    schema, err := reflector.Reflect(&TestStruct{})
    if err != nil {
        log.Fatal(err)
    }

    j, err := json.MarshalIndent(schema, "", " ")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(j))
}

output

{
 "properties": {
  "time": {
   "examples": [
    "Xiao",
    "Dao"
   ],
   "items": {
    "examples": [
     "Xiao"
    ],
    "type": "string"
   },
   "type": "array"
  }
 },
 "type": "object"
}

But write the example below, and the one that comes out is different

apiSchema := jsonrpc.OpenAPI{}
    apiSchema.Reflector().SpecEns().Info.Title = "JSON-RPC Example"
    apiSchema.Reflector().SpecEns().Info.Version = "v1.2.3"

    apiSchema.Reflector().SpecEns().Info.WithDescription("This app showcases a trivial JSON-RPC API.")

    h := &jsonrpc.Handler{}
    h.OpenAPI = &apiSchema
    h.Validator = &jsonrpc.JSONSchemaValidator{}
    h.SkipResultValidation = true

    type inp struct {
        Name []string `json:"name" examples:"[\"Xiao\",\"Dao\"]" example:"Xiao"`
    }

    type out struct {
        Len int `json:"len"`
    }

    u := usecase.NewInteractor[*inp, out](func(ctx context.Context, input *inp, output *out) error {
        output.Len = len(input.Name)

        return nil
    })
    u.SetName("nameLength")

    h.Add(u)

    r := chi.NewRouter()

    r.Mount("/rpc", h)

    // Swagger UI endpoint at /docs.
    r.Method(http.MethodGet, "/docs/openapi.json", h.OpenAPI)

    r.Mount("/docs", v3cdn.NewHandlerWithConfig(swgui.Config{
        Title:       apiSchema.Reflector().Spec.Info.Title,
        SwaggerJSON: "/docs/openapi.json",
        BasePath:    "/docs",
        SettingsUI:  jsonrpc.SwguiSettings(nil, "/rpc"),
    }))

    // Start server.
    log.Println("http://localhost:8011/docs")

    if err := http.ListenAndServe(":8011", r); err != nil {
        log.Fatal(err)
    }

output

"Inp": {
    "type": "object",
    "properties": {
     "name": {
      "type": "array",
      "items": {
       "type": "string",
       "example": "Xiao"
      },
      "nullable": true,
      "example": "Xiao"
     }
    }
   },

Why are the examples parsed out of these two writing methods different?

vearutop commented 2 years ago

JSON-RPC library uses OpenAPI 3.0.3 to hack around documentation. Unfortunately, that version of OpenAPI only supports single example in schema. OpenAPI library uses jsonschema-go to reflect schemas and then adapt them to own format.

Here is where first example is taken: https://github.com/swaggest/openapi-go/blob/v0.2.20/openapi3/jsonschema.go#L230