from_swagger/main.go

192 lines
4.8 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"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)
if err := os.WriteFile("models.kt", []byte(res["models"]), 0600); err != nil {
panic(err)
}
if err := os.WriteFile("client.kt", []byte(res["client"]), 0600); err != nil {
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")
for path, methods := range config.Paths {
for method, v := range methods {
sbClient.WriteString(fmt.Sprintf("\t@%s(value = \"%s\")\n", toMicronautKotlinMethod(method), path))
sbClient.WriteString(fmt.Sprintf("\tfun %s(\n", v.OperationID))
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()))
}
// todo body and test
sbClient.WriteString("\t")
sbClient.WriteString(fmt.Sprintf("): HttpResponse<%s>\n", v.Responses.Num200.Content.ApplicationJSON.Schema.toKt()))
sbClient.WriteString("\n")
}
}
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]
}