mirror of
https://github.com/LukeHagar/theschemagen.git
synced 2025-12-06 04:21:44 +00:00
196 lines
4.5 KiB
Go
196 lines
4.5 KiB
Go
package theschemagen
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func PrettyPrint(v interface{}, format string) {
|
|
var b []byte
|
|
var err error
|
|
|
|
switch format {
|
|
case "json":
|
|
b, err = json.MarshalIndent(v, "", " ")
|
|
case "yaml":
|
|
b, err = yaml.Marshal(v)
|
|
default:
|
|
b, err = yaml.Marshal(v)
|
|
}
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
fmt.Println(string(b))
|
|
}
|
|
|
|
type SchemaObject struct {
|
|
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
|
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
|
Items interface{} `json:"items,omitempty" yaml:"items,omitempty"`
|
|
Examples []interface{} `json:"examples,omitempty" yaml:"examples,omitempty"`
|
|
Properties map[string]SchemaObject `json:"properties,omitempty" yaml:"properties,omitempty"`
|
|
}
|
|
|
|
func ConvertNumber(number float64) SchemaObject {
|
|
output := SchemaObject{}
|
|
if IsInteger(number) {
|
|
output.Type = "integer"
|
|
if number < 2147483647 && number > -2147483647 {
|
|
output.Format = "int32"
|
|
} else if IsSafeInteger(number) {
|
|
output.Format = "int64"
|
|
}
|
|
} else {
|
|
output.Type = "number"
|
|
}
|
|
|
|
output.Examples = []interface{}{number}
|
|
|
|
return output
|
|
}
|
|
|
|
func ConvertArray(array []interface{}) SchemaObject {
|
|
output := SchemaObject{Type: "array", Items: nil}
|
|
var outputItems []SchemaObject
|
|
|
|
for _, entry := range array {
|
|
|
|
objectMap := ConvertObject(entry)
|
|
isDuplicate := false
|
|
|
|
for _, item := range outputItems {
|
|
hasSameTypeAndFormat := item.Type == objectMap.Type && item.Format == objectMap.Format
|
|
hasSameProperties := item.Properties != nil && objectMap.Properties != nil &&
|
|
CompareKeys(item.Properties, objectMap.Properties)
|
|
if hasSameTypeAndFormat || hasSameProperties {
|
|
isDuplicate = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !isDuplicate {
|
|
outputItems = append(outputItems, objectMap)
|
|
}
|
|
|
|
}
|
|
|
|
if len(outputItems) > 1 {
|
|
output.Items = map[string]interface{}{"oneOf": outputItems}
|
|
} else {
|
|
output.Items = outputItems[0]
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
func ConvertString(str string) SchemaObject {
|
|
output := SchemaObject{Type: "string"}
|
|
|
|
regxDate := regexp.MustCompile(`^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$`)
|
|
regxDateTime := regexp.MustCompile(`^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]Z$`)
|
|
|
|
if regxDateTime.MatchString(str) {
|
|
output.Format = "date-time"
|
|
} else if regxDate.MatchString(str) {
|
|
output.Format = "date"
|
|
}
|
|
|
|
output.Examples = []interface{}{str}
|
|
|
|
return output
|
|
}
|
|
|
|
func ConvertObject(input interface{}) SchemaObject {
|
|
switch v := input.(type) {
|
|
case nil:
|
|
return SchemaObject{Type: "null"}
|
|
case float64:
|
|
return ConvertNumber(v)
|
|
case []interface{}:
|
|
return ConvertArray(v)
|
|
case map[string]interface{}:
|
|
output := SchemaObject{Type: "object", Properties: make(map[string]SchemaObject)}
|
|
for key, val := range v {
|
|
output.Properties[key] = ConvertObject(val)
|
|
}
|
|
return output
|
|
case string:
|
|
return ConvertString(v)
|
|
case bool:
|
|
output := SchemaObject{Type: "boolean"}
|
|
|
|
output.Examples = []interface{}{v}
|
|
|
|
return output
|
|
default:
|
|
panic("Invalid type for conversion")
|
|
}
|
|
}
|
|
|
|
func ConvertJSONToOAS(input string) SchemaObject {
|
|
var obj map[string]interface{}
|
|
err := json.Unmarshal([]byte(input), &obj)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return ConvertObject(obj)
|
|
}
|
|
|
|
func ConvertObjectToOAS(input map[string]interface{}) SchemaObject {
|
|
return ConvertObject(input)
|
|
}
|
|
|
|
var ignoredWords = []string{"the", "a", "an", "of", "to", "in", "for", "with", "on", "at", "from", "by", "and"}
|
|
|
|
func ConvertSummaryToOperationId(summary string) string {
|
|
words := strings.Split(summary, " ")
|
|
var filteredWords []string
|
|
for i, word := range words {
|
|
if i == 0 {
|
|
filteredWords = append(filteredWords, strings.ToLower(string(word[0]))+word[1:])
|
|
} else {
|
|
if !Contains(ignoredWords, strings.ToLower(word)) {
|
|
filteredWords = append(filteredWords, cases.Title(language.English, cases.NoLower).String(word))
|
|
}
|
|
}
|
|
}
|
|
return strings.Join(filteredWords, "")
|
|
}
|
|
|
|
func Contains(arr []string, str string) bool {
|
|
for _, v := range arr {
|
|
if v == str {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func CompareKeys(m1, m2 map[string]SchemaObject) bool {
|
|
if len(m1) != len(m2) {
|
|
return false
|
|
}
|
|
for k := range m1 {
|
|
if _, ok := m2[k]; !ok {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func IsInteger(n float64) bool {
|
|
return n == float64(int(n))
|
|
}
|
|
|
|
func IsSafeInteger(n float64) bool {
|
|
return n <= float64(int64(^uint(0)>>1)) && n >= float64(int64(^uint(0)>>1)*-1)
|
|
}
|