从Go结构生成OpenAPI XML模型

huangapple go评论91阅读模式
英文:

Generate OpenAPI XML model from Go structure

问题

有没有办法使用golang结构生成一个OpenAPI规范文档(针对XML)?我的结构体使用了encoding/xml注解,像这样:

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

我想自动生成一个符合这些注解的OpenAPI模型。

英文:

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

答案1

得分: 2

你可以使用标准库中的reflect包来检查结构体及其标签,可以使用gopkg.in/yaml.v3包来生成Open API格式。你只需要编写逻辑,将你的类型转换为与Open API文档结构相匹配的类型。

以下是一个示例,注意这只是一个不完整的示例,因此不能直接使用:

// 声明一个与OpenAPI的yaml文档匹配的结构体
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"`
}
// 编写一个marshal函数,将给定的类型转换为上面声明的结构体
// - 此示例仅转换普通结构体
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 { // 没有名称?
				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("不支持的类型")
}
// 让所有的类型实现yaml.Marshaler接口
// 委托给上面实现的marshal函数
func (e Error) MarshalYAML() (interface{}, error) {
    return marshalOpenAPI(e)
}
// 将类型进行编组
yaml.Marshal(map[string]map[string]interface{}{
	"schemas": {
        "error": Error{},
        // ...
    },
})

playground上试一试。

英文:

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&#39;s yaml document
type DataType struct {
	Type  string               `yaml:&quot;type,omitempty&quot;`
	Props map[string]*DataType `yaml:&quot;properties,omitempty&quot;`
	XML   *XML                 `yaml:&quot;xml,omitempty&quot;`
}
type XML struct {
	Name string `yaml:&quot;name,omitempty&quot;`
	Attr bool   `yaml:&quot;attribute,omitempty&quot;`
}
// 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: &quot;object&quot;}

		for i := 0; i &lt; rt.NumField(); i++ {
			f := rt.Field(i)
			tag := strings.Split(f.Tag.Get(&quot;xml&quot;), &quot;,&quot;)
			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] = &amp;DataType{
				Type: goTypeToOpenAPIType(f.Type),
			}
			if len(tag) &gt; 1 &amp;&amp; tag[1] == &quot;attr&quot; {
				obj.Props[name].XML = &amp;XML{Attr: true}
			}
		}

		return obj, nil
	}
	return nil, fmt.Errorf(&quot;unsupported type&quot;)
}
// 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{}{
	&quot;schemas&quot;: {
        &quot;error&quot;: Error{},
        // ...
    },
})

Try it on playground.

huangapple
  • 本文由 发表于 2021年11月19日 22:58:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/70036803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定