+12
-4
json2go.go
+12
-4
json2go.go
···
16
16
)
17
17
18
18
type Transformer struct {
19
-
structName string
19
+
structName string
20
+
currentIndent int
20
21
}
21
22
22
23
func NewTransformer() *Transformer {
···
32
33
}
33
34
34
35
t.structName = structName
36
+
t.currentIndent = 0
35
37
36
38
var input any
37
39
if err := json.Unmarshal([]byte(jsonStr), &input); err != nil {
···
82
84
f.field = "NotNamedField"
83
85
}
84
86
87
+
// increase indentation in case of building new struct
88
+
t.currentIndent++
85
89
fieldType := t.getGoType(fieldName, f.type_)
90
+
t.currentIndent--
86
91
87
92
// todo: toggle json tags generation
88
93
jsonTag := fmt.Sprintf("`json:\"%s\"`", f.field)
89
94
90
-
// todo: figure out the indentation, since it might have nested struct
95
+
indent := strings.Repeat("\t", t.currentIndent+1)
91
96
fields.WriteString(fmt.Sprintf(
92
-
"%s %s %s\n",
97
+
"%s%s %s %s\n",
98
+
indent,
93
99
fieldName,
94
100
fieldType,
95
101
jsonTag,
96
102
))
97
103
}
98
104
99
-
return fmt.Sprintf("struct {\n%s}", fields.String())
105
+
return fmt.Sprintf("struct {\n%s%s}",
106
+
fields.String(),
107
+
strings.Repeat("\t", t.currentIndent))
100
108
}
101
109
102
110
func (t *Transformer) getGoType(fieldName string, value any) string {
+6
-5
json2go_internal_test.go
+6
-5
json2go_internal_test.go
···
14
14
"age": float64(20),
15
15
},
16
16
output: "struct {" +
17
-
field("Age", "int") +
18
-
field("Username", "string") + "\n}",
17
+
field(1, "Age", "int") +
18
+
field(1, "Username", "string") +
19
+
"\n}",
19
20
},
20
21
"empty slice": {
21
22
value: make([]any, 0),
···
82
83
"active": true,
83
84
},
84
85
output: "struct {" +
85
-
field("Active", "bool", "active") +
86
+
field(1, "Active", "bool", "active") +
86
87
"\n}",
87
88
},
88
89
"with no named field": {
89
90
input: map[string]any{"": "user"},
90
91
output: "struct {" +
91
-
field("NotNamedField", "string", "NotNamedField") +
92
+
field(1, "NotNamedField", "string", "NotNamedField") +
92
93
"\n}",
93
94
},
94
95
}
···
113
114
"struct": {
114
115
input: map[string]any{"field": false},
115
116
output: c + "struct {" +
116
-
field("Field", "bool") + "\n}",
117
+
field(1, "Field", "bool") + "\n}",
117
118
},
118
119
"slice": {
119
120
input: []any{"asdf", "jkl;"},
+22
-21
json2go_test.go
+22
-21
json2go_test.go
···
8
8
"testing"
9
9
)
10
10
11
-
func field(name, type_ string, json_ ...string) string {
11
+
func field(indentLvl int, name, type_ string, json_ ...string) string {
12
+
indent := strings.Repeat("\t", indentLvl)
12
13
if strings.Contains(type_, "struct") {
13
-
return fmt.Sprintf("\n%s %s", name, type_)
14
+
return fmt.Sprintf("\n%s%s %s", indent, name, type_)
14
15
}
15
16
16
17
tag := strings.ToLower(name)
17
18
if len(json_) == 1 {
18
19
tag = json_[0]
19
20
}
20
-
return fmt.Sprintf("\n%s %s `json:\"%s\"`", name, type_, tag)
21
+
return fmt.Sprintf("\n%s%s %s `json:\"%s\"`", indent, name, type_, tag)
21
22
}
22
23
23
24
func TestTransformer_Transform(t *testing.T) {
···
30
31
"simple object": {
31
32
input: `{"name": "Olex", "active": true, "age": 420}`,
32
33
output: "type Out struct {" +
33
-
field("Active", "bool") +
34
-
field("Age", "int") +
35
-
field("Name", "string") +
34
+
field(1, "Active", "bool") +
35
+
field(1, "Age", "int") +
36
+
field(1, "Name", "string") +
36
37
"\n}",
37
38
},
38
39
"invalid json": {
···
54
55
"snake_case to CamelCase": {
55
56
input: `{"first_name": "Bob", "last_name": "Bobberson"}`,
56
57
output: "type Out struct {" +
57
-
field("FirstName", "string", "first_name") +
58
-
field("LastName", "string", "last_name") +
58
+
field(1, "FirstName", "string", "first_name") +
59
+
field(1, "LastName", "string", "last_name") +
59
60
"\n}",
60
61
},
61
62
"nested object and array": {
62
63
input: `{"user": {"name": "Alice", "score": 95.5}, "tags": ["go", "json"]}`,
63
64
output: "type Out struct {" +
64
-
field("Tags", "[]string") +
65
-
field("User", "struct {") +
66
-
field("Name", "string") +
67
-
field("Score", "float64") +
68
-
"\n} `json:\"user\"`" +
65
+
field(1, "Tags", "[]string") +
66
+
field(1, "User", "struct {") +
67
+
field(2, "Name", "string") +
68
+
field(2, "Score", "float64") +
69
+
"\n\t} `json:\"user\"`" +
69
70
"\n}",
70
71
},
71
72
"empty nested object": {
72
73
input: `{"user": {}}`,
73
74
output: "type Out struct {" +
74
-
field("User", "struct {") +
75
-
"\n} `json:\"user\"`" +
75
+
field(1, "User", "struct {") +
76
+
"\n\t} `json:\"user\"`" +
76
77
"\n}",
77
78
},
78
79
"array of object": {
79
80
input: `[{"name": "John"}, {"name": "Jane"}]`,
80
81
output: "type Out []struct {" +
81
-
field("Name", "string") +
82
+
field(1, "Name", "string") +
82
83
"\n}",
83
84
},
84
85
"empty array": {
85
86
input: `{"items": []}`,
86
87
output: "type Out struct {" +
87
-
field("Items", "[]any") +
88
+
field(1, "Items", "[]any") +
88
89
"\n}",
89
90
},
90
91
"null": {
91
92
input: `{"item": null}`,
92
93
output: `type Out struct {` +
93
-
field("Item", "any") +
94
+
field(1, "Item", "any") +
94
95
"\n}",
95
96
},
96
97
"numbers": {
97
98
input: `{"pos": 123, "neg": -321, "float": 420.69}`,
98
99
output: "type Out struct {" +
99
-
field("Float", "float64") +
100
-
field("Neg", "int") +
101
-
field("Pos", "int") +
100
+
field(1, "Float", "float64") +
101
+
field(1, "Neg", "int") +
102
+
field(1, "Pos", "int") +
102
103
"\n}",
103
104
},
104
105
}