Home > Enterprise >  Generate OpenAPI XML model from Go structure
Generate OpenAPI XML model from Go structure

Time:11-20

Is there any way to generate a OpenAPI specification document for XML using golang structure? My structures are annotated with encoding/xml annotations like this:

type Error struct {
    Text      string `xml:",chardata"`
    Type      string `xml:"Type,attr"`
    Code      string `xml:"Code,attr"`
    ShortText string `xml:"ShortText,attr"`
}

I would like to generate a OpenAPI model automatically, which respect these annotations

CodePudding user response:

You can use the reflect package from the standard library to inspect the struct and its tags and you can use the gopkg.in/yaml.v3 package to generate the Open API format. You just need to write the logic that translates your type into another, one that matches the structure of the Open API document.

Here's an example of how you could approach this, note that it is incomplete and should therefore not be used as is:

// declare a structure that matches the OpenAPI's yaml document
type DataType struct {
    Type  string               `yaml:"type,omitempty"`
    Props map[string]*DataType `yaml:"properties,omitempty"`
    XML   *XML                 `yaml:"xml,omitempty"`
}
type XML struct {
    Name string `yaml:"name,omitempty"`
    Attr bool   `yaml:"attribute,omitempty"`
}
// write a marshal func that converts a given type to the structure declared above
// - this example converts only plain structs
func marshalOpenAPI(v interface{}) (interface{}, error) {
    rt := reflect.TypeOf(v)
    if rt.Kind() == reflect.Struct {
        obj := DataType{Type: "object"}

        for i := 0; i < rt.NumField(); i   {
            f := rt.Field(i)
            tag := strings.Split(f.Tag.Get("xml"), ",")
            if len(tag) == 0 || len(tag[0]) == 0 { // no name?
                continue
            }
            if obj.Props == nil {
                obj.Props = make(map[string]*DataType)
            }

            name := tag[0]
            obj.Props[name] = &DataType{
                Type: goTypeToOpenAPIType(f.Type),
            }
            if len(tag) > 1 && tag[1] == "attr" {
                obj.Props[name].XML = &XML{Attr: true}
            }
        }

        return obj, nil
    }
    return nil, fmt.Errorf("unsupported type")
}
// have all your types implement the yaml.Marshaler interface by
// delegating to the marshal func implemented above
func (e Error) MarshalYAML() (interface{}, error) {
    return marshalOpenAPI(e)
}
// marshal the types
yaml.Marshal(map[string]map[string]interface{}{
    "schemas": {
        "error": Error{},
        // ...
    },
})

Try it on playground.

CodePudding user response:

I think your only option here is to specify format. You can add a personal format. Here for more informations : string formats

  • Related