Skip to content

Commit ac4a052

Browse files
committed
code restructuring
1 parent 9908a89 commit ac4a052

File tree

4 files changed

+414
-205
lines changed

4 files changed

+414
-205
lines changed

builder.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package dynamic_struct
2+
3+
import "reflect"
4+
5+
type (
6+
Builder interface {
7+
AddField(name string, typ interface{}, tag string) Builder
8+
RemoveField(name string) Builder
9+
HasField(name string) bool
10+
GetField(name string) FieldConfig
11+
Build() interface{}
12+
}
13+
14+
FieldConfig interface {
15+
SetType(typ interface{}) FieldConfig
16+
SetTag(tag string) FieldConfig
17+
}
18+
19+
builder struct {
20+
fields map[string]*fieldConfig
21+
}
22+
23+
fieldConfig struct {
24+
typ interface{}
25+
tag string
26+
}
27+
)
28+
29+
func NewBuilder() Builder {
30+
return &builder{
31+
fields: map[string]*fieldConfig{},
32+
}
33+
}
34+
35+
func (b *builder) AddField(name string, typ interface{}, tag string) Builder {
36+
b.fields[name] = &fieldConfig{
37+
typ: typ,
38+
tag: tag,
39+
}
40+
41+
return b
42+
}
43+
44+
func (b *builder) RemoveField(name string) Builder {
45+
delete(b.fields, name)
46+
47+
return b
48+
}
49+
50+
func (b *builder) HasField(name string) bool {
51+
_, ok := b.fields[name]
52+
return ok
53+
}
54+
55+
func (b *builder) GetField(name string) FieldConfig {
56+
return b.fields[name]
57+
}
58+
59+
func (b *builder) Build() interface{} {
60+
var structFields []reflect.StructField
61+
62+
for name, field := range b.fields {
63+
structFields = append(structFields, reflect.StructField{
64+
Name: name,
65+
Type: reflect.TypeOf(field.typ),
66+
Tag: reflect.StructTag(field.tag),
67+
})
68+
}
69+
70+
return reflect.New(reflect.StructOf(structFields)).Interface()
71+
}
72+
73+
func (f *fieldConfig) SetType(typ interface{}) FieldConfig {
74+
f.typ = typ
75+
return f
76+
}
77+
78+
func (f *fieldConfig) SetTag(tag string) FieldConfig {
79+
f.tag = tag
80+
return f
81+
}

struct_test.go renamed to builder_test.go

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,37 @@ import (
1212
)
1313

1414
type (
15-
StructTestSuite struct {
15+
BuilderTestSuite struct {
1616
suite.Suite
1717

1818
builder Builder
1919
}
2020
)
2121

22-
func TestStructTestSuite(t *testing.T) {
23-
suite.Run(t, &StructTestSuite{})
22+
func TestBuilderTestSuite(t *testing.T) {
23+
suite.Run(t, &BuilderTestSuite{})
2424
}
2525

26-
func (t *StructTestSuite) SetupTest() {
26+
func (t *BuilderTestSuite) SetupTest() {
27+
integer := 0
28+
str := ""
29+
float := 0.0
30+
boolean := false
31+
2732
t.builder = NewBuilder().
28-
AddField("Integer", 0, "").
29-
AddField("Text", "", "").
30-
AddField("Float", 0.0, "").
31-
AddField("Boolean", false, "").
33+
AddField("Integer", integer, "").
34+
AddField("Text", str, "").
35+
AddField("Float", float, "").
36+
AddField("Boolean", boolean, "").
37+
AddField("NilInteger", &integer, "").
38+
AddField("NilText", &str, "").
39+
AddField("NilFloat", &float, "").
40+
AddField("NilBoolean", &boolean, "").
3241
AddField("Slice", []int{}, "").
3342
AddField("Anonymous", "", "")
3443
}
3544

36-
func (t *StructTestSuite) TestJson() {
45+
func (t *BuilderTestSuite) TestJson() {
3746
t.builder.GetField("Integer").SetTag(`json:"int"`)
3847
t.builder.GetField("Text").SetTag(`json:"someText"`)
3948
t.builder.GetField("Float").SetTag(`json:"double"`)
@@ -47,22 +56,34 @@ func (t *StructTestSuite) TestJson() {
4756
"double": 123.45,
4857
"Boolean": true,
4958
"Slice": [1, 2, 3],
50-
"Anonymous": "avoid to read"
59+
"Anonymous": "avoid to read",
60+
"NilFloat": 567
5161
}
5262
`)
5363

5464
err := json.Unmarshal(data, &value)
5565
t.NoError(err)
5666

57-
vReader := NewReader(value)
58-
t.Equal(123, vReader.Int("Integer"))
59-
t.Equal("example", vReader.String("Text"))
60-
t.Equal(123.45, vReader.Float64("Float"))
61-
t.Equal(true, vReader.Bool("Boolean"))
62-
t.Equal("", vReader.String("Anonymous"))
67+
var result map[string]interface{}
68+
err = NewReader(value).MapTo(&result)
69+
t.NoError(err)
70+
71+
float := 567.0
72+
t.Equal(map[string]interface{}{
73+
"int": 123.0,
74+
"someText": "example",
75+
"double": 123.45,
76+
"Boolean": true,
77+
"Slice": []interface{}{1.0, 2.0, 3.0},
78+
"NilInteger": nil,
79+
"NilFloat": float,
80+
"NilBoolean": nil,
81+
"NilText": nil,
82+
}, result)
83+
6384
}
6485

65-
func (t *StructTestSuite) TestFormAndConform() {
86+
func (t *BuilderTestSuite) TestFormAndConform() {
6687
t.builder.GetField("Integer").SetTag(`form:"int"`)
6788
t.builder.GetField("Text").SetTag(`form:"someText" conform:"trim"`)
6889
t.builder.GetField("Float").SetTag(`form:"double"`)
@@ -76,6 +97,7 @@ func (t *StructTestSuite) TestFormAndConform() {
7697
"Boolean": []string{"on"},
7798
"Slice": []string{"1", "2", "3"},
7899
"Anonymous": []string{"avoid to read"},
100+
"NilFloat": []string{"567"},
79101
}
80102

81103
decoder := form.NewDecoder()
@@ -85,15 +107,26 @@ func (t *StructTestSuite) TestFormAndConform() {
85107
err = conform.Strings(value)
86108
t.NoError(err)
87109

88-
vReader := NewReader(value)
89-
t.Equal(123, vReader.Int("Integer"))
90-
t.Equal("example", vReader.String("Text"))
91-
t.Equal(123.45, vReader.Float64("Float"))
92-
t.Equal(true, vReader.Bool("Boolean"))
93-
t.Equal("", vReader.String("Anonymous"))
110+
var result map[string]interface{}
111+
err = NewReader(value).MapTo(&result)
112+
t.NoError(err)
113+
114+
float := 567.0
115+
t.Equal(map[string]interface{}{
116+
"Integer": 123.0,
117+
"Text": "example",
118+
"Float": 123.45,
119+
"Boolean": true,
120+
"Anonymous": "",
121+
"Slice": []interface{}{1.0, 2.0, 3.0},
122+
"NilInteger": nil,
123+
"NilFloat": float,
124+
"NilBoolean": nil,
125+
"NilText": nil,
126+
}, result)
94127
}
95128

96-
func (t *StructTestSuite) TestValidate() {
129+
func (t *BuilderTestSuite) TestValidate() {
97130
t.builder.GetField("Integer").SetTag(`validate:"gt=0"`)
98131
t.builder.GetField("Text").SetTag(`validate:"required"`)
99132
value := t.builder.Build()
@@ -104,4 +137,4 @@ func (t *StructTestSuite) TestValidate() {
104137
validationErrors, ok := err.(validator.ValidationErrors)
105138
t.True(ok)
106139
t.Len(validationErrors, 2)
107-
}
140+
}

0 commit comments

Comments
 (0)