package main import ( "encoding/json" "fmt" "os" "sort" "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("res/models.kt", []byte(res["models"]), 0600); err != nil { panic(err) } if err := os.WriteFile("res/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") 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)) } sbClient.WriteString(fmt.Sprintf("\t@%s(value = \"%s\")\n", toMicronautKotlinMethod(method), path)) sbClient.WriteString(fmt.Sprintf("\tfun %s(", v.OperationID)) if len(v.Parameters) != 0 || v.RequestBody != nil { sbClient.WriteString("\n") } 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())) } 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") } sbClient.WriteString(")") resp := v.Responses.Num200.Content.ApplicationJSON.Schema.toKt() if resp != "" { sbClient.WriteString(fmt.Sprintf(": HttpResponse<%s>", resp)) } sbClient.WriteString("\n\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] } 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 }