-
Notifications
You must be signed in to change notification settings - Fork 0
/
addStructsFromJSON.go
114 lines (101 loc) · 3.49 KB
/
addStructsFromJSON.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package jenshared
import (
"fmt"
"strings"
"time"
"github.com/dave/jennifer/jen"
"github.com/google/uuid"
)
func addStructsFromJSON(f *jen.File, data interface{}, config *Config) {
typeItemsMap := createTypeItemsMapFromJSON(data, config)
addStructs(f, typeItemsMap, config)
}
func createTypeItemsMapFromJSON(data interface{}, config *Config) TypeItemsMap {
typeItemsMap := make(TypeItemsMap)
return parseInterface(typeItemsMap, data, config)
}
func parseInterface(items TypeItemsMap, data interface{}, config *Config) TypeItemsMap {
switch concreteVal := data.(type) {
case bool, float64, string:
items[config.RootName] = TypeItems{{Name: config.RootName, Type: inferDataType(concreteVal, config)}}
case map[string]interface{}:
parseMap(items, concreteVal, config.RootName, config)
case []interface{}:
diveTopLevelArray(items, concreteVal, config, "[]")
}
return items
}
func diveTopLevelArray(items TypeItemsMap, data []interface{}, config *Config, acc string) TypeItemsMap {
if len(data) > 0 {
switch firstVal := data[0].(type) {
case bool, float64, string:
items[config.RootName] = TypeItems{{Name: config.RootName, Type: fmt.Sprintf("%s%s", acc, inferDataType(firstVal, config))}}
case map[string]interface{}:
arrTitle := fmt.Sprintf("%sArray", config.RootName)
items[arrTitle] = TypeItems{{Name: arrTitle, Type: fmt.Sprintf("%s%s", acc, config.RootName)}}
parseMap(items, firstVal, config.RootName, config)
case []interface{}:
diveTopLevelArray(items, firstVal, config, fmt.Sprintf("%s[]", acc))
}
}
return items
}
func parseMap(items TypeItemsMap, data map[string]interface{}, parent string, config *Config) TypeItemsMap {
for key, val := range data {
title := strings.Title(key)
switch concreteVal := val.(type) {
case map[string]interface{}:
items[title] = make(TypeItems, 0)
items[parent] = append(items[parent], TypeItem{Name: key, Type: title})
parseMap(items, concreteVal, title, config)
case []interface{}:
items[parent] = append(items[parent], TypeItem{Name: key, Type: fmt.Sprintf("[]%s", title)})
parseFirstIndexArray(items, concreteVal, title, config)
default:
items[parent] = append(items[parent], TypeItem{Name: key, Type: inferDataType(concreteVal, config)})
}
}
return items
}
func parseFirstIndexArray(items TypeItemsMap, array []interface{}, parent string, config *Config) TypeItemsMap {
if len(array) > 0 {
switch concreteVal := array[0].(type) {
case map[string]interface{}:
parseMap(items, concreteVal, parent, config)
case []interface{}:
InterfaceArrayOuter:
for key, itemArray := range items {
for index, item := range itemArray {
if item.Title() == parent {
items[key][index].Type = fmt.Sprintf("[]%s", item.Type)
parseFirstIndexArray(items, concreteVal, parent, config)
break InterfaceArrayOuter
}
}
}
default:
DefaultOuter:
for key, itemArray := range items {
for index, item := range itemArray {
if item.Title() == parent && strings.HasSuffix(item.Type, parent) {
items[key][index].Type = fmt.Sprintf("%s%s", strings.TrimSuffix(item.Type, parent), inferDataType(concreteVal, config))
break DefaultOuter
}
}
}
}
}
return items
}
func inferDataType(value interface{}, config *Config) string {
valType := fmt.Sprintf("%T", value)
if valType == "string" {
if _, err := time.Parse(config.TimeFormat, value.(string)); err == nil {
return "time"
}
if _, err := uuid.Parse(value.(string)); err == nil {
return "uuid"
}
}
return valType
}