forked from gookit/goutil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert.go
167 lines (141 loc) · 3.92 KB
/
convert.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package maputil
import (
"errors"
"reflect"
"strings"
"github.com/gookit/goutil/arrutil"
"github.com/gookit/goutil/comdef"
"github.com/gookit/goutil/reflects"
"github.com/gookit/goutil/strutil"
)
// KeyToLower convert keys to lower case.
func KeyToLower(src map[string]string) map[string]string {
newMp := make(map[string]string, len(src))
for k, v := range src {
k = strings.ToLower(k)
newMp[k] = v
}
return newMp
}
// ToStringMap convert map[string]any to map[string]string
func ToStringMap(src map[string]any) map[string]string {
strMp := make(map[string]string, len(src))
for k, v := range src {
strMp[k] = strutil.SafeString(v)
}
return strMp
}
// CombineToSMap combine two string-slice to SMap(map[string]string)
func CombineToSMap(keys, values []string) SMap {
return arrutil.CombineToSMap(keys, values)
}
// CombineToMap combine two any slice to map[K]V. alias of arrutil.CombineToMap
func CombineToMap[K comdef.SortedType, V any](keys []K, values []V) map[K]V {
return arrutil.CombineToMap(keys, values)
}
// ToAnyMap convert map[TYPE1]TYPE2 to map[string]any
func ToAnyMap(mp any) map[string]any {
amp, _ := TryAnyMap(mp)
return amp
}
// TryAnyMap convert map[TYPE1]TYPE2 to map[string]any
func TryAnyMap(mp any) (map[string]any, error) {
if aMp, ok := mp.(map[string]any); ok {
return aMp, nil
}
rv := reflect.Indirect(reflect.ValueOf(mp))
if rv.Kind() != reflect.Map {
return nil, errors.New("input is not a map value")
}
anyMp := make(map[string]any, rv.Len())
for _, key := range rv.MapKeys() {
anyMp[key.String()] = rv.MapIndex(key).Interface()
}
return anyMp, nil
}
// HTTPQueryString convert map[string]any data to http query string.
func HTTPQueryString(data map[string]any) string {
ss := make([]string, 0, len(data))
for k, v := range data {
ss = append(ss, k+"="+strutil.QuietString(v))
}
return strings.Join(ss, "&")
}
// StringsMapToAnyMap convert map[string][]string to map[string]any
//
// Example:
// {"k1": []string{"v1", "v2"}, "k2": []string{"v3"}}
// =>
// {"k": []string{"v1", "v2"}, "k2": "v3"}
//
// mp := StringsMapToAnyMap(httpReq.Header)
func StringsMapToAnyMap(ssMp map[string][]string) map[string]any {
if len(ssMp) == 0 {
return nil
}
anyMp := make(map[string]any, len(ssMp))
for k, v := range ssMp {
if len(v) == 1 {
anyMp[k] = v[0]
continue
}
anyMp[k] = v
}
return anyMp
}
// ToString simple and quickly convert map[string]any to string.
func ToString(mp map[string]any) string {
if mp == nil {
return ""
}
if len(mp) == 0 {
return "{}"
}
buf := make([]byte, 0, len(mp)*16)
buf = append(buf, '{')
for k, val := range mp {
buf = append(buf, k...)
buf = append(buf, ':')
str := strutil.QuietString(val)
buf = append(buf, str...)
buf = append(buf, ',', ' ')
}
// remove last ', '
buf = append(buf[:len(buf)-2], '}')
return strutil.Byte2str(buf)
}
// ToString2 simple and quickly convert a map to string.
func ToString2(mp any) string {
return NewFormatter(mp).Format()
}
// FormatIndent format map data to string with newline and indent.
func FormatIndent(mp any, indent string) string {
return NewFormatter(mp).WithIndent(indent).Format()
}
/*************************************************************
* Flat convert tree map to flatten key-value map.
*************************************************************/
// Flatten convert tree map to flat key-value map.
//
// Examples:
//
// {"top": {"sub": "value", "sub2": "value2"} }
// ->
// {"top.sub": "value", "top.sub2": "value2" }
func Flatten(mp map[string]any) map[string]any {
if mp == nil {
return nil
}
flatMp := make(map[string]any, len(mp)*2)
reflects.FlatMap(reflect.ValueOf(mp), func(path string, val reflect.Value) {
flatMp[path] = val.Interface()
})
return flatMp
}
// FlatWithFunc flat a tree-map with custom collect handle func
func FlatWithFunc(mp map[string]any, fn reflects.FlatFunc) {
if mp == nil || fn == nil {
return
}
reflects.FlatMap(reflect.ValueOf(mp), fn)
}