@@ -5,11 +5,13 @@ import (
5
5
json "github.com/json-iterator/go"
6
6
"regexp"
7
7
"strings"
8
+ "sync"
8
9
)
9
10
10
11
// NewMap 新建数据
11
12
// 递归(惰性,用到才解析)获取所有可以解析数据
12
13
func NewMap (i interface {}, codec ... codec.Interface ) * Map {
14
+ //一般用NewMap之后,肯定会获取值的,固直接decode
13
15
return newMap (i , codec ... ).decode ()
14
16
}
15
17
@@ -18,7 +20,7 @@ func newMap(i interface{}, codec ...codec.Interface) *Map {
18
20
return val
19
21
}
20
22
m := & Map {Var : New (i )}
21
- if len (codec ) > 0 {
23
+ if len (codec ) > 0 && codec [ 0 ] != nil {
22
24
m .codec = codec [0 ]
23
25
}
24
26
return m
@@ -27,142 +29,175 @@ func newMap(i interface{}, codec ...codec.Interface) *Map {
27
29
// Map deep 惰性解析 DMap
28
30
// 万次解析0.09s
29
31
type Map struct {
30
- * Var //值
31
- Extend //继承
32
- valMap map [string ]* Map //map
33
- valList []* Map //list
34
- de bool //是否已解析
35
- codec codec.Interface //编解码
32
+ * Var //值
33
+ Extend //继承
34
+ object map [string ]* Map //对象实例
35
+ array []* Map //数组实例
36
+ codec codec.Interface //编解码
37
+ once sync.Once //惰性加载,解析一次
38
+ hasSet bool //设置了新数据
36
39
}
37
40
38
- func (this * Map ) IsDefault (key ... string ) bool {
39
- if len (key ) == 0 {
40
- return this .Var .IsDefault ()
41
- }
42
- return this .Get (key [0 ]).IsDefault (key [1 :]... )
43
- }
44
-
45
- func (this * Map ) IsNumber (key ... string ) bool {
46
- if len (key ) == 0 {
47
- return this .Var .IsNumber ()
48
- }
49
- return this .Get (key [0 ]).IsNumber (key [1 :]... )
41
+ // GetVar 实现Extend的接口,继承Extend的接口
42
+ func (this * Map ) GetVar (key string ) * Var {
43
+ return this .Get (key ).Var
50
44
}
51
45
52
- func (this * Map ) IsString (key ... string ) bool {
53
- if len (key ) == 0 {
54
- return this .Var .IsString ()
46
+ // Map 获取对象map,不安全,不推荐使用
47
+ func (this * Map ) Map () map [string ]* Map {
48
+ for _ , v := range this .object {
49
+ v .decode ()
55
50
}
56
- return this .Get ( key [ 0 ]). IsString ( key [ 1 :] ... )
51
+ return this .object
57
52
}
58
53
59
- func (this * Map ) IsInt (key ... string ) bool {
60
- if len (key ) == 0 {
61
- return this .Var .IsInt ()
54
+ // List 获取数组,不安全,不推荐使用
55
+ func (this * Map ) List () []* Map {
56
+ for _ , v := range this .array {
57
+ v .decode ()
62
58
}
63
- return this .Get ( key [ 0 ]). IsInt ( key [ 1 :] ... )
59
+ return this .array
64
60
}
65
61
66
- func (this * Map ) IsFloat (key ... string ) bool {
67
- if len (key ) == 0 {
68
- return this .Var .IsFloat ()
62
+ // Get 获取Map,可以根据分隔符来获取更深入的数据
63
+ // 分隔符.和小数冲突,现在暂时不支持查询key是小数的对象或者key有.和[]
64
+ // 例如使用key(a.b[0]) 可以从 {"a":{"b":[0,1]}} 得到0的Map
65
+ func (this * Map ) Get (key string ) * Map {
66
+ data := this
67
+ for _ , v := range this .getKeys (key ) {
68
+ switch k := v .(type ) {
69
+ case string :
70
+ data = data .getObject (k , false )
71
+ case int :
72
+ data = data .getArray (k )
73
+ }
69
74
}
70
- return this . Get ( key [ 0 ]). IsFloat ( key [ 1 :] ... )
75
+ return data . refresh ( )
71
76
}
72
77
73
- func (this * Map ) IsBool (key ... string ) bool {
74
- if len (key ) == 0 {
75
- return this .Var .IsBool ()
78
+ // Set 设置数据,会覆盖原先的数据,
79
+ // key可以使用分割符号.和[],分别对应对象和数组,例 a.b[1].c[1][3]
80
+ // 分隔符.和小数冲突,现在暂时不支持查询key是小数的对象或者key有.和[]
81
+ // 例如使用Set("a.b[0]",100) 可以使 {"a":{"b":[0,1]}} 变成 {"a":{"b":[100,1]}}
82
+ // 假如对象key不存在,会自动添加
83
+ // 如果数组的下标不存在,则不会自动添加,例如设置了下标100,补充99个nil值不是很合理
84
+ // 如果设置了nil,对应json的null
85
+ func (this * Map ) Set (key string , value interface {}) * Map {
86
+ data := this
87
+ for _ , v := range this .getKeys (key ) {
88
+ //所有的父级都打上标记,方便后续判断
89
+ data .hasSet = true
90
+ switch k := v .(type ) {
91
+ case string :
92
+ data = data .getObject (k , true )
93
+ case int :
94
+ data = data .getArray (k )
95
+ }
76
96
}
77
- return this .Get (key [0 ]).IsBool (key [1 :]... )
97
+ * data = * newMap (value , this .codec ) //覆盖原先的Map
98
+ return this
78
99
}
79
100
80
- func (this * Map ) IsTime (key ... string ) bool {
81
- if len (key ) == 0 {
82
- return this .Var .IsTime ()
101
+ // Append 追加元素,只对数组有效
102
+ // key可以使用分割符号.和[],分别对应对象和数组,例 a.b[1].c[1][3]
103
+ // 分隔符.和小数冲突,现在暂时不支持查询key是小数的对象或者key有.和[]
104
+ // 例如 {"a":{"n":1},"b":[0,1]} 使用Append("b",3,4)后,得到 {"a":{"n":1},"b":[0,1,3,4]}
105
+ // 但是使用Append("a",3,4)后是无变化的,因为a是对象,可以使用Set("a",[]int{0,1,3,4})得到一样的结果
106
+ // 如果设置了nil,对应json的null
107
+ func (this * Map ) Append (key string , value ... interface {}) * Map {
108
+ data := this
109
+ for _ , v := range this .getKeys (key ) {
110
+ //所有的父级都打上标记,方便后续判断
111
+ data .hasSet = true
112
+ switch k := v .(type ) {
113
+ case string :
114
+ data = data .getObject (k , true )
115
+ case int :
116
+ data = data .getArray (k )
117
+ }
83
118
}
84
- return this .Get (key [0 ]).IsTime (key [1 :]... )
85
- }
86
-
87
- func (this * Map ) IsArray (key ... string ) bool {
88
- if len (key ) == 0 {
89
- return this .Var .IsArray ()
119
+ if len (data .object ) == 0 {
120
+ //假如不是对象的情况下生效
121
+ for _ , v := range value {
122
+ data .array = append (data .array , newMap (v , this .codec ))
123
+ }
124
+ data .hasSet = true
125
+ data .Var .Set (data .encode ())
90
126
}
91
- return this . Get ( key [ 0 ]). IsArray ( key [ 1 :] ... )
127
+ return this
92
128
}
93
129
94
- func (this * Map ) IsPointer (key ... string ) bool {
95
- if len (key ) == 0 {
96
- return this .Var .IsPointer ()
97
- }
98
- return this .Get (key [0 ]).IsPointer (key [1 :]... )
130
+ // String 重构下Var的String函数,针对Set/Append后的惰性更新
131
+ func (this * Map ) String (def ... string ) string {
132
+ this .refresh ()
133
+ return this .Var .String (def ... )
99
134
}
100
135
101
- func (this * Map ) IsNil (key ... string ) bool {
102
- if len (key ) == 0 {
103
- return this .Var .IsNil ()
136
+ // refresh 刷新,因为是惰性加载/更新,固有个刷新函数
137
+ // 正常情况是使用不到,除非直接
138
+ func (this * Map ) refresh () * Map {
139
+ if this .hasSet {
140
+ this .Var .Set (this .encode ())
141
+ this .hasSet = false
104
142
}
105
- return this . Get ( key [ 0 ]). IsNil ( key [ 1 :] ... )
143
+ return this
106
144
}
107
145
108
- func (this * Map ) GoString () string {
109
- return this .Var .String ()
110
- }
146
+ /*
111
147
112
- func (this * Map ) GetVar (key string ) * Var {
113
- return this .Get (key ).Var
114
- }
115
148
116
- func (this * Map ) Map () map [string ]* Map {
117
- for _ , v := range this .valMap {
118
- v .decode ()
119
- }
120
- return this .valMap
121
- }
122
149
123
- func (this * Map ) List () []* Map {
124
- for _ , v := range this .valList {
125
- v .decode ()
126
- }
127
- return this .valList
128
- }
150
+ */
129
151
130
- func (this * Map ) Get (key string ) * Map {
131
- data := this
152
+ // 获取对象的key或者数组的下标,用类型来区分,字符表示对象的key,数字表示数字的下标
153
+ // 先分割.,再正则匹配[0-9]+,例如 a.key[1][0] ,得到 {"a","key",1,0}
154
+ func (this * Map ) getKeys (key string ) []interface {} {
155
+ keys := []interface {}(nil )
132
156
for _ , v := range strings .Split (key , "." ) {
133
- list := regexp .MustCompile (`\[[0-9]+\]` ).FindAllString (v , - 1 )
134
- lengthAll := 0
135
- for i , k := range list {
136
- length := len (k )
137
- lengthAll += length
138
- list [i ] = k [1 : length - 1 ]
139
- }
140
- v = v [:len (v )- lengthAll ]
141
- if len (v ) > 0 {
142
- data = data .getMap (v )
157
+ indexList := []interface {}(nil )
158
+ length := 0
159
+ for _ , k := range regexp .MustCompile (`\[[0-9]+\]` ).FindAllString (v , - 1 ) {
160
+ length += len (k )
161
+ //去除[]后的数字,即数组的下标
162
+ indexList = append (indexList , Int (k [1 :len (k )- 1 ]))
143
163
}
144
- for _ , k := range list {
145
- data = data .getList (Int (k ))
164
+ if vKey := v [:len (v )- length ]; len (vKey ) > 0 {
165
+ //对象的key,例 key[1][0] 中间的key
166
+ keys = append (keys , v [:len (v )- length ])
146
167
}
168
+ //数组的下标
169
+ keys = append (keys , indexList ... )
147
170
}
148
- return data
171
+ return keys
149
172
}
150
173
151
- func (this * Map ) getMap (key string ) * Map {
152
- data , ok := this .valMap [key ]
174
+ // 根据key获取对象
175
+ func (this * Map ) getObject (key string , setIfNotExist bool ) * Map {
176
+ data , ok := this .object [key ]
153
177
if ok {
154
178
return data .decode ()
155
179
}
156
- return NewMap (nil , this .codec )
180
+ m := NewMap (nil , this .codec )
181
+ if setIfNotExist {
182
+ this .object [key ] = m
183
+ }
184
+ return m
157
185
}
158
186
159
- func (this * Map ) getList (idx int ) * Map {
160
- if idx < len (this .valList ) {
161
- return this .valList [idx ].decode ()
187
+ // 根据下标获取数组的元素,支持python的负数下标,
188
+ // 例如-1表示获取数组的最后一个元素
189
+ func (this * Map ) getArray (idx int ) * Map {
190
+ if idx >= 0 && idx < len (this .array ) {
191
+ return this .array [idx ].decode ()
192
+ }
193
+ //对负数的支持,例如-1表示获取数组的最后一个元素,参考python
194
+ if idx < 0 && - idx <= len (this .array ) {
195
+ return this .array [len (this .array )+ idx ].decode ()
162
196
}
163
197
return NewMap (nil , this .codec )
164
198
}
165
199
200
+ // 获取编解码函数
166
201
func (this * Map ) getParse () func (data []byte , v interface {}) error {
167
202
if this .codec == nil {
168
203
if codec .Default != nil {
@@ -174,39 +209,71 @@ func (this *Map) getParse() func(data []byte, v interface{}) error {
174
209
}
175
210
176
211
func (this * Map ) decode () * Map {
177
- if ! this .de {
212
+ this .once . Do ( func () {
178
213
parse := this .getParse ()
179
- this .valMap = make (map [string ]* Map )
214
+ this .object = make (map [string ]* Map )
180
215
if ! this .Var .IsNil () {
181
216
switch val := this .Var .Val ().(type ) {
182
217
case map [string ]interface {}:
183
218
for i , v := range val {
184
- this .valMap [i ] = newMap (v , codec .Json )
219
+ this .object [i ] = newMap (v , codec .Json )
220
+ }
221
+ case map [interface {}]interface {}:
222
+ for i , v := range val {
223
+ this .object [String (i )] = newMap (v , codec .Json )
185
224
}
186
225
case []interface {}:
187
226
for _ , v := range val {
188
- this .valList = append (this .valList , newMap (v , codec .Json ))
227
+ this .array = append (this .array , newMap (v , codec .Json ))
189
228
}
190
229
default :
191
230
m := make (map [string ]interface {})
192
231
bs := []byte (this .Var .String ())
193
232
if err := parse (bs , & m ); err == nil {
194
233
for i , v := range m {
195
- this .valMap [ i ] = newMap (v , codec .Json )
234
+ this .object [ String ( i ) ] = newMap (v , codec .Json )
196
235
}
197
236
} else {
198
237
var list []interface {}
199
238
if err := parse (bs , & list ); err == nil {
200
239
for _ , v := range list {
201
- this .valList = append (this .valList , newMap (v , codec .Json ))
240
+ this .array = append (this .array , newMap (v , codec .Json ))
202
241
}
203
242
}
204
243
}
205
244
206
245
}
207
246
}
208
247
this .Extend = NewExtend (this )
209
- this .de = true
210
- }
248
+ })
211
249
return this
212
250
}
251
+
252
+ func (this * Map ) encode () interface {} {
253
+
254
+ //判断是否设置过新值,没解析直接取var的值
255
+ if ! this .hasSet {
256
+ return this .Var .Val ()
257
+ }
258
+
259
+ if len (this .array ) > 0 {
260
+ //数组
261
+ list := []interface {}(nil )
262
+ for _ , v := range this .array {
263
+ list = append (list , v .encode ())
264
+ }
265
+ return list
266
+ }
267
+
268
+ if len (this .object ) > 0 {
269
+ //对象
270
+ object := map [string ]interface {}{}
271
+ for k , v := range this .object {
272
+ object [k ] = v .encode ()
273
+ }
274
+ return object
275
+ }
276
+
277
+ return this .Var .Val ()
278
+
279
+ }
0 commit comments