google / docsy

A set of Hugo doc templates for launching open source content.
https://docsy.dev
Apache License 2.0
2.63k stars 904 forks source link

openapi and go-gin: accessing internal model info #2051

Closed kayshav closed 4 months ago

kayshav commented 4 months ago

I am using swagger/openapi to write a simple REST interface. In openapi I specify that some parameters are "required". For, example, the /api/v1/device is a REST endpoint. The Device object has some attributes, but Serial, Vendor, and Model are required.

In the openapi.yaml file, I have for Device the following:

required: [Serial, Vendor, Model]

The generated code with "openapi-generator-cli generate -g go-gin-server" generated the following. type Device struct { Name stringjson:"name,omitempty" Description stringjson:"description,omitempty"` Serial stringjson:"Serial" // The name of the vendor (or manufacturer). Vendor stringjson:"Vendor" Model stringjson:"Model" }

What is surprising to me is that the Device struct does not have the "required" tag for Serial, Vendor, and Model. My thinking is that when I use the ShouldBindJSON() method to bind the incoming data to a Deviceobject, if any of the required fields are missing, the ShouldBindJSON call should fail. However, that's not what I observed and the binding just goes through without any error.

When searching for more info, I bumped into this post https://gin-gonic.com/docs/examples/binding-and-validation/. Here, I see the following decoration for the struct fields.

User stringform:"user" json:"user" xml:"user" binding:"required"``

With the added "binding:required", the ShouldBindJSON call fails if any of required fields are missing.

I'm not sure how I can make go-gin add the "binding:required" decoration to my Device struct when it generates code from the openapi spec. I prefer not to manually edit the generated code from go-gin to add the decorations because the generated files are over-written every time I run make command.

Questions:

  1. Is there any way to instruct go-gin to generate code with the "binding:required" decorartion?
  2. Or, if #1 is not possible, I am thinking that I could write code to examine the generated struct and check each field in a struct to see if it is required (missing the "omitempty" decoration). But, how do I get access to the metadata that go-gin uses internally. go-gin does have an option to output its models (debugModels=true), which just dumps the model info to screen. But, I need access to the models in my code. If I could get access to the internal metadata, I can write a simple piece of code with go generics to process my struct and verify that "required" fields are present. I can also write code using go reflection package to examine the metadata, if the metadata is available.

Appreciate any pointers. -kD

kayshav commented 4 months ago

There's one solution that is feasible. The decorations are part of the struct, and therefore I can use reflection on the struct to determine the decorations on each struct field. Here is a piece of code I used to print the decorations

package main

import (
     "fmt"
     "reflect"
)

type Device struct {
        Name string `json:"name,omitempty"`
        Description string `json:"description,omitempty"`
        Serial string `json:"Serial"`
}
func main() {

    var dev Device
    rType := reflect.TypeOf(dev)
    // Traverse through all the fields of a struct.
    if rType.Kind() == reflect.Struct {
        for i := 0; i < rType.NumField(); i++ {
            fieldValue := rType.Field(i)
            fmt.Printf("fld: %v\n", fieldValue)
        }
    }
}

This generates the output: fld: {Name string json:"name,omitempty" 0 [0] false} fld: {Description string json:"description,omitempty" 16 [1] false} fld: {Serial string json:"Serial" 32 [2] false}

Using the above approach, I can write a generic piece of code using go generics to examine if a struct has the 'omitempty' decoration then check the incoming value object of the struct and verify that non-omitempty fields are filled.

Wondering if there are any better solutions.

emckean commented 4 months ago

Hi, this does not seem related to the Docsy project so I am closing this issue.