forked from m7shapan/njson
/
unmarshal.go
99 lines (77 loc) · 2.09 KB
/
unmarshal.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
package njson
import (
"encoding/json"
"errors"
"reflect"
"github.com/tidwall/gjson"
)
const tag string = "njson"
// Unmarshal used to unmarshal nested json using "njson" tag
func Unmarshal(data []byte, v interface{}) (err error) {
// catch code panic and return error message
defer func() {
if r := recover(); r != nil {
switch x := r.(type) {
case string:
err = errors.New(x)
case error:
err = x
default:
err = errors.New("Unknown panic")
}
}
}()
elem := reflect.ValueOf(v).Elem()
typeOfT := elem.Type()
for i := 0; i < elem.NumField(); i++ {
field := elem.Field(i)
if !(validTag(typeOfT.Field(i)) && field.CanSet()) {
continue
}
// get field value by tag
result := gjson.GetBytes(data, typeOfT.Field(i).Tag.Get(tag))
var value interface{}
if isStructureType(field.Kind().String()) {
value = parseStructureType(result, field.Type())
} else {
// set field value depend on it's data type
value = parseDataType(result, field.Kind().String())
}
if v != nil {
elem.Field(i).Set(reflect.ValueOf(value))
}
}
return nil
}
func unmarshalSlice(results []gjson.Result, field reflect.Type) interface{} {
newSlice := reflect.MakeSlice(field, 0, 0)
for i := 0; i < len(results); i++ {
var value interface{}
if isStructureType(field.Elem().String()) {
value = parseStructureType(results[i], field.Elem())
} else {
// set field value depend on it's data type
value = parseDataType(results[i], field.Elem().String())
}
if value != nil {
newSlice = reflect.Append(newSlice, reflect.ValueOf(value))
}
}
return newSlice.Interface()
}
func unmarshalMap(raw string, field reflect.Type) interface{} {
m := reflect.New(reflect.MapOf(field.Key(), field.Elem())).Interface()
err := json.Unmarshal([]byte(raw), m)
if err != nil {
panic(err)
}
return reflect.Indirect(reflect.ValueOf(m)).Interface()
}
func unmarshalStruct(raw string, field reflect.Type) interface{} {
v := reflect.New(field).Interface()
err := Unmarshal([]byte(raw), v)
if err != nil {
panic(err)
}
return reflect.Indirect(reflect.ValueOf(v)).Interface()
}