from_swagger/main.go

222 lines
5.5 KiB
Go
Raw Normal View History

2024-02-18 13:12:52 +00:00
package main
import (
"encoding/json"
"fmt"
"os"
2024-02-18 20:10:41 +00:00
"sort"
2024-02-18 13:12:52 +00:00
"strings"
)
type config struct {
Openapi string `json:"openapi"`
Info struct {
Title string `json:"title"`
Description string `json:"description"`
Version string `json:"version"`
} `json:"info"`
Paths map[string]map[string]struct {
Tags []string `json:"tags"`
Summary string `json:"summary"`
OperationID string `json:"operationId"`
Parameters []struct {
Name string `json:"name"`
In string `json:"in"`
Schema property `json:"schema"`
} `json:"parameters"`
RequestBody *struct {
Content struct {
ApplicationJSON struct {
Schema property `json:"schema"`
} `json:"application/json"`
} `json:"content"`
Required bool `json:"required"`
} `json:"requestBody"`
Responses struct {
Num200 struct {
Description string `json:"description"`
Content struct {
ApplicationJSON struct {
Schema property `json:"schema"`
} `json:"application/json"`
} `json:"content"`
} `json:"200"`
} `json:"responses"`
} `json:"paths"`
Components struct {
Models map[string]struct {
Type string `json:"type"`
Properties map[string]property `json:"properties"`
} `json:"schemas"`
} `json:"components"`
}
type property struct {
Type string `json:"type"`
Format string `json:"format"`
Nullable bool `json:"nullable"`
Ref string `json:"$ref"`
AllOf []struct {
Ref string `json:"$ref"`
} `json:"allOf"`
Items struct {
Ref string `json:"$ref"`
} `json:"items"`
}
func (p *property) toKt() string {
sb := strings.Builder{}
if p.Type != "" {
sb.WriteString(fmt.Sprintf("%s", toMicronautKotlinType(*p)))
}
if p.Ref != "" {
sb.WriteString(fmt.Sprintf("%s", refToName(p.Ref)))
}
if len(p.AllOf) != 0 {
sb.WriteString(fmt.Sprintf("%s", refToName(p.AllOf[0].Ref)))
}
if p.Nullable {
sb.WriteString(fmt.Sprintf("?"))
}
return sb.String()
}
func main() {
b, err := os.ReadFile("swaggers/example_1.json")
if err != nil {
panic(err)
}
config := &config{}
if err := json.Unmarshal(b, config); err != nil {
panic(err)
}
res := toMicronautKotlin(config)
2024-02-18 20:10:41 +00:00
if err := os.WriteFile("res/models.kt", []byte(res["models"]), 0600); err != nil {
2024-02-18 13:12:52 +00:00
panic(err)
}
2024-02-18 20:10:41 +00:00
if err := os.WriteFile("res/client.kt", []byte(res["client"]), 0600); err != nil {
2024-02-18 13:12:52 +00:00
panic(err)
}
}
func toMicronautKotlin(config *config) map[string]string {
sbModels := strings.Builder{}
sbModels.WriteString("package models\n\n")
for modelName, model := range config.Components.Models {
sbModels.WriteString(fmt.Sprintf("data class %s(\n", modelName))
for name, value := range model.Properties {
sbModels.WriteString(fmt.Sprintf("\tvar %s: ", name))
sbModels.WriteString(value.toKt())
sbModels.WriteString(",\n")
}
sbModels.WriteString(")\n\n")
}
sbClient := strings.Builder{}
sbClient.WriteString("package client\n\n")
sbClient.WriteString("import io.micronaut.http.HttpResponse\n")
sbClient.WriteString("import io.micronaut.http.annotation.*\n")
sbClient.WriteString("import io.micronaut.http.client.annotation.Client\n")
sbClient.WriteString("\n")
sbClient.WriteString("@Client(value = \"INPUT URL\")\n")
sbClient.WriteString("interface GDSClient {\n\n")
2024-02-18 20:10:41 +00:00
pathKeys := getSortKeys(config.Paths)
for _, path := range pathKeys {
methods := config.Paths[path]
methodKeys := getSortKeys(methods)
for _, method := range methodKeys {
v := methods[method]
if v.Summary != "" {
sbClient.WriteString(fmt.Sprintf("\t// %s\n", v.Summary))
}
2024-02-18 13:12:52 +00:00
sbClient.WriteString(fmt.Sprintf("\t@%s(value = \"%s\")\n", toMicronautKotlinMethod(method), path))
2024-02-18 20:10:41 +00:00
sbClient.WriteString(fmt.Sprintf("\tfun %s(", v.OperationID))
2024-02-18 13:12:52 +00:00
2024-02-18 20:10:41 +00:00
if len(v.Parameters) != 0 || v.RequestBody != nil {
sbClient.WriteString("\n")
}
2024-02-18 13:12:52 +00:00
for _, p := range v.Parameters {
sbClient.WriteString("\t\t")
switch p.In {
case "header":
sbClient.WriteString("@Header")
case "path":
sbClient.WriteString("@PathVariable")
default:
sbClient.WriteString(fmt.Sprintf("(type %s not support)", p.In))
}
sbClient.WriteString(fmt.Sprintf(" %s: %s,\n", p.Name, p.Schema.toKt()))
}
2024-02-18 20:10:41 +00:00
if v.RequestBody != nil {
sbClient.WriteString(fmt.Sprintf("\t\t@Body %s: %s,\n", "body", v.RequestBody.Content.ApplicationJSON.Schema.toKt()))
}
if len(v.Parameters) != 0 || v.RequestBody != nil {
sbClient.WriteString("\t")
}
2024-02-18 13:12:52 +00:00
2024-02-18 20:10:41 +00:00
sbClient.WriteString(")")
resp := v.Responses.Num200.Content.ApplicationJSON.Schema.toKt()
if resp != "" {
sbClient.WriteString(fmt.Sprintf(": HttpResponse<%s>", resp))
}
sbClient.WriteString("\n\n")
2024-02-18 13:12:52 +00:00
}
}
sbClient.WriteString("}\n\n")
return map[string]string{
"models": sbModels.String(),
"client": sbClient.String(),
}
}
func toMicronautKotlinType(prop property) string {
switch prop.Type {
case "string":
return "String"
case "integer":
return "Int"
case "boolean":
return "Boolean"
case "number":
return "Double"
case "array":
return fmt.Sprintf("List<%s>", refToName(prop.Items.Ref))
}
return fmt.Sprintf("type %s not support", prop.Type)
}
func toMicronautKotlinMethod(method string) string {
switch method {
case "get":
return "Get"
case "post":
return "Post"
case "put":
return "Put"
case "delete":
return "Delete"
}
return fmt.Sprintf("mmethod %s not support", method)
}
func refToName(ref string) string {
arr := strings.Split(ref, "/")
return arr[len(arr)-1]
}
2024-02-18 20:10:41 +00:00
func getSortKeys[T any](m map[string]T) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}