/
fields.go
105 lines (97 loc) · 2.03 KB
/
fields.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
package fields
import (
"encoding/json"
"strings"
)
func NewCleaner(x string) Cleaner {
y := Cleaner{false, make(map[string]bool)}
if x != "" {
if strings.HasPrefix(x, "-") {
x = x[1:]
y.exclude = true
}
for _, field := range strings.Split(x, ",") {
y.fields[field] = true
}
}
return y
}
type Cleaner struct {
exclude bool
fields map[string]bool
}
func (f Cleaner) Clean(x, y interface{}) (bool, error) {
if len(f.fields) == 0 {
return false, nil
}
v, err := json.Marshal(x)
if err != nil {
return false, err
}
data := make(map[string]interface{})
if err := json.Unmarshal(v, &data); err != nil {
return false, err
}
f.cleanItem([]string{}, data)
w, err := json.Marshal(data)
if err != nil {
return false, err
}
if err := json.Unmarshal(w, &y); err != nil {
return false, err
}
return true, nil
}
func (f Cleaner) WillExclude(x string) bool {
if len(f.fields) == 0 {
return false
}
if f.matches(x) {
return f.exclude
} else {
return !f.exclude
}
}
func (f Cleaner) matches(x string) bool {
for y := range f.fields {
if strings.HasPrefix(x, y) || strings.HasPrefix(y, x) {
return true
}
}
return false
}
func (f Cleaner) cleanItem(path []string, item interface{}) {
if mapItem, ok := item.(map[string]interface{}); ok {
for k, v := range mapItem {
fieldPath := strings.Join(append(path, k), ".")
_, pathIn := f.fields[fieldPath]
parentPathIn := pathIn
if !parentPathIn {
for k := range f.fields {
if strings.HasPrefix(k, fieldPath) {
parentPathIn = true
break
}
}
}
if f.exclude && !pathIn || !f.exclude && parentPathIn {
if !pathIn {
f.cleanItem(append(path, k), v)
}
} else {
delete(mapItem, k)
}
}
} else if arrayItem, ok := item.([]interface{}); ok {
for i := range arrayItem {
f.cleanItem(path, arrayItem[i])
}
}
}
func (f Cleaner) WithoutPrefix(prefix string) Cleaner {
y := Cleaner{f.exclude, map[string]bool{}}
for k, v := range f.fields {
y.fields[strings.TrimPrefix(k, prefix)] = v
}
return y
}