-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterfacestruct.go
91 lines (77 loc) · 2.39 KB
/
interfacestruct.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
package interfacestruct
import (
"fmt"
"reflect"
"strconv"
"time"
)
// Data generic struct used for converting to an []interface{} into structures like Member, Child, OrderNumber
type DataGeneric[T any] struct {
Data T
}
type RequestData struct {
Values [][]interface{}
}
func (dt *DataGeneric[T]) ConvertToInterfaceRequest() RequestData {
var requestData RequestData
v := reflect.ValueOf(dt.Data)
datai := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
datai[i] = v.Field(i).Interface()
}
requestData.Values = append(requestData.Values, datai)
return requestData
}
func (dt *DataGeneric[T]) ConvertToStruct(data []interface{}) (T, error) {
structType := reflect.TypeOf(dt.Data)
structValue := reflect.ValueOf(&dt.Data).Elem()
if len(data) != structType.NumField() {
return dt.Data, fmt.Errorf("invalid input length")
}
for i := 0; i < structType.NumField(); i++ {
fieldType := structType.Field(i)
fieldValue := structValue.Field(i)
if i >= len(data) {
return dt.Data, fmt.Errorf("not enough data to populate all fields")
}
// Convert the interface value to the type of the struct field
if reflect.TypeOf(data[i]) != fieldType.Type {
value, err := getAssertedTypedValue(data[i], fieldType)
if err != nil {
return dt.Data, err
}
fieldValue.Set(value)
} else {
fieldValue.Set(reflect.ValueOf(data[i]))
}
}
return dt.Data, nil
}
func getAssertedTypedValue(data interface{}, fieldType reflect.StructField) (reflect.Value, error) {
if fieldType.Type.Kind() == reflect.Int {
d, err := strconv.Atoi(data.(string))
return reflect.ValueOf(d), err
}
if fieldType.Type.Kind() == reflect.Uint64 {
d, err := strconv.ParseUint(data.(string), 10, 64)
return reflect.ValueOf(d), err
}
if fieldType.Type.Kind() == reflect.Float32 {
d, err := strconv.ParseFloat(data.(string), 32)
return reflect.ValueOf(d), err
}
if fieldType.Type.Kind() == reflect.Float64 {
d, err := strconv.ParseFloat(data.(string), 64)
return reflect.ValueOf(d), err
}
if fieldType.Type == reflect.TypeOf(time.Time{}) {
layout := "2006-01-02T15:04:05.999999999Z07:00"
d, err := time.Parse(layout, data.(string))
return reflect.ValueOf(d), err
}
if fieldType.Type.Kind() == reflect.Bool {
d, err := strconv.ParseBool(data.(string))
return reflect.ValueOf(d), err
}
return reflect.ValueOf(nil), fmt.Errorf("type mismatch for field %s", fieldType.Name)
}