1
- package json_diff
1
+ /*
2
+ * Copyright 2021 Junebao
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ package decode
2
19
3
20
import (
21
+ "bytes"
4
22
"fmt"
23
+ "regexp"
5
24
"strconv"
6
25
"strings"
7
26
)
8
27
28
+ var keyReplaceRegexp = regexp .MustCompile (`~0*1` )
29
+
30
+ // KeyReplace 转义 key 中的特殊字符
31
+ // "/" 会被替换成 "~1"
32
+ // "~1" 会被替换成 "~01"
33
+ // "~01" 会被替换为 "~001"
34
+ // "~001" 会被替换为 "~0001"
35
+ // 依此类推
36
+ func KeyReplace (key string ) string {
37
+ resList := keyReplaceRegexp .FindAllStringIndex (key , - 1 )
38
+ buff := bytes .NewBufferString ("" )
39
+ pre := 0
40
+ for _ , res := range resList {
41
+ buff .WriteString (key [pre :res [0 ]])
42
+ buff .WriteRune ('~' )
43
+ for i := 1 ; i < res [1 ]- res [0 ]; i ++ {
44
+ buff .WriteRune ('0' )
45
+ }
46
+ buff .WriteRune ('1' )
47
+ pre = res [1 ]
48
+ }
49
+ buff .WriteString (key [pre :])
50
+ return strings .ReplaceAll (buff .String (), "/" , "~1" )
51
+ }
52
+
53
+ func KeyRestore (key string ) string {
54
+ key = strings .ReplaceAll (key , "~1" , "/" )
55
+ resList := keyReplaceRegexp .FindAllStringIndex (key , - 1 )
56
+ buff := bytes .NewBufferString ("" )
57
+ pre := 0
58
+ for _ , res := range resList {
59
+ buff .WriteString (key [pre :res [0 ]])
60
+ buff .WriteRune ('~' )
61
+ for i := 3 ; i < res [1 ]- res [0 ]; i ++ {
62
+ buff .WriteRune ('0' )
63
+ }
64
+ buff .WriteRune ('1' )
65
+ pre = res [1 ]
66
+ }
67
+ buff .WriteString (key [pre :])
68
+ return buff .String ()
69
+ }
70
+
9
71
type JsonNodeType uint8
10
72
11
73
const (
@@ -23,15 +85,15 @@ const (
23
85
)
24
86
25
87
func (jt JsonNodeType ) String () string {
26
- switch jt {
27
- case JsonNodeTypeValue :
28
- return "value"
29
- case JsonNodeTypeSlice :
30
- return "slice"
31
- case JsonNodeTypeObject :
32
- return "object"
33
- }
34
- return ""
88
+ switch jt {
89
+ case JsonNodeTypeValue :
90
+ return "value"
91
+ case JsonNodeTypeSlice :
92
+ return "slice"
93
+ case JsonNodeTypeObject :
94
+ return "object"
95
+ }
96
+ return ""
35
97
}
36
98
37
99
// JsonNode 以树的形式组织 Json 中的每一项数据。
@@ -51,13 +113,23 @@ func (jt JsonNodeType) String() string {
51
113
// 一个 Json 字节数组可以使用 Unmarshal 反序列化为 JsonNode 对象,
52
114
// JsonNode 对象也可以使用 Marshal 序列化为 Json 字节数组
53
115
type JsonNode struct {
54
- Type JsonNodeType `json:"type"`
55
- Hash string `json:"hash"`
56
- Key string `json:"key"`
57
- Value interface {} `json:"value"` // 保存 JsonNodeTypeValue 类型对象的值
58
- Children []* JsonNode `json:"children"` // 保存 JsonNodeTypeSlice 类型对象的值
59
- ChildrenMap map [string ]* JsonNode `json:"children_map"` // 保存 JsonNodeTypeObject 类型对象的值
60
- Level int64 `json:"level"` // 该 node 所处的层级
116
+ Type JsonNodeType `json:"type"`
117
+ Hash string `json:"hash"`
118
+ Key string `json:"key"`
119
+ Value interface {} `json:"value"` // 保存 JsonNodeTypeValue 类型对象的值
120
+ Children []* JsonNode `json:"children"` // 保存 JsonNodeTypeSlice 类型对象的值
121
+ ChildrenMap map [string ]* JsonNode `json:"children_map"` // 保存 JsonNodeTypeObject 类型对象的值
122
+ Level int64 `json:"level"` // 该 node 所处的层级
123
+ originalValue []byte // 保存反序列化时最原始的值,避免序列化动态类型转换
124
+ }
125
+
126
+ func newOriginalValueNode (ov []byte , value interface {}, level int ) * JsonNode {
127
+ return & JsonNode {
128
+ Type : JsonNodeTypeValue ,
129
+ Value : value ,
130
+ Level : int64 (level ),
131
+ originalValue : ov ,
132
+ }
61
133
}
62
134
63
135
func NewObjectNode (key string , childrenMap map [string ]* JsonNode , level int ) * JsonNode {
@@ -134,6 +206,17 @@ func (jn *JsonNode) ADD(key interface{}, value *JsonNode) error {
134
206
return nil
135
207
}
136
208
209
+ // Append 为当前 JsonNodeTypeSlice 节点追加子对象。
210
+ // 只能用于 JsonNodeTypeSlice 类型的节点。
211
+ func (jn * JsonNode ) Append (v * JsonNode ) error {
212
+ if jn .Type != JsonNodeTypeSlice {
213
+ return GetJsonNodeError ("append" ,
214
+ "cannot append an object to a node of type JsonNodeTypeSlice" )
215
+ }
216
+ jn .Children = append (jn .Children , v )
217
+ return nil
218
+ }
219
+
137
220
// AddPath 为 node 的 path 路径处的对象添加一个子节点
138
221
// path 路径表示的是子节点加入后的路径, 以 "/" 开头
139
222
func AddPath (node * JsonNode , path string , value * JsonNode ) error {
@@ -196,7 +279,7 @@ func (jn *JsonNode) Equal(patch *JsonNode) bool {
196
279
func (jn * JsonNode ) find (paths []string ) (* JsonNode , bool ) {
197
280
root := jn
198
281
for _ , key := range paths {
199
- key = keyRestore (key )
282
+ key = KeyRestore (key )
200
283
switch root .Type {
201
284
case JsonNodeTypeObject :
202
285
r , ok := root .ChildrenMap [key ]
@@ -400,42 +483,42 @@ func CopyPath(node *JsonNode, from, path string) error {
400
483
}
401
484
402
485
func ATestPath (srcNode * JsonNode , path string , value * JsonNode ) error {
403
- f , ok := srcNode .Find (path )
404
- if ! ok {
405
- return GetJsonNodeError ("test" , fmt .Sprintf ("%s not find" , path ))
406
- }
407
- if f .Type != value .Type {
408
- return GetJsonNodeError ("test" ,
409
- fmt .Sprintf ("types are not equal, one is %s, another is %s" ,
410
- f .Type .String (), value .Type .String ()))
411
- }
412
- switch value .Type {
413
- case JsonNodeTypeValue :
414
- // [{"op": "test", "path": "a/b/c", "value":"123"}]
415
- if f .Value != value .Value {
416
- return GetJsonNodeError ("test" , valueAreNotEqual (f .Value , value .Value ))
417
- }
418
- case JsonNodeTypeSlice :
419
- // [{"op": "test", "path": "a/b/c", "value":[123, 456]}]
420
- if len (f .Children ) != len (value .Children ) {
421
- return GetJsonNodeError ("test" , valueAreNotEqual (f .Children , value .Children ))
422
- }
423
- for i , v := range value .Children {
424
- if ! v .Equal (f .Children [i ]) {
425
- return GetJsonNodeError ("test" , valueAreNotEqual (v , f .Children [i ]))
426
- }
427
- }
428
- case JsonNodeTypeObject :
429
- if len (f .ChildrenMap ) != len (value .ChildrenMap ) {
430
- return GetJsonNodeError ("test" , valueAreNotEqual (f .ChildrenMap , value .ChildrenMap ))
431
- }
432
- for k , v := range value .ChildrenMap {
433
- if ! v .Equal (f .ChildrenMap [k ]) {
434
- return GetJsonNodeError ("test" , valueAreNotEqual (v , f .ChildrenMap [k ]))
435
- }
436
- }
437
- }
438
- return nil
486
+ f , ok := srcNode .Find (path )
487
+ if ! ok {
488
+ return GetJsonNodeError ("test" , fmt .Sprintf ("%s not find" , path ))
489
+ }
490
+ if f .Type != value .Type {
491
+ return GetJsonNodeError ("test" ,
492
+ fmt .Sprintf ("types are not equal, one is %s, another is %s" ,
493
+ f .Type .String (), value .Type .String ()))
494
+ }
495
+ switch value .Type {
496
+ case JsonNodeTypeValue :
497
+ // [{"op": "test", "path": "a/b/c", "value":"123"}]
498
+ if f .Value != value .Value {
499
+ return GetJsonNodeError ("test" , valueAreNotEqual (f .Value , value .Value ))
500
+ }
501
+ case JsonNodeTypeSlice :
502
+ // [{"op": "test", "path": "a/b/c", "value":[123, 456]}]
503
+ if len (f .Children ) != len (value .Children ) {
504
+ return GetJsonNodeError ("test" , valueAreNotEqual (f .Children , value .Children ))
505
+ }
506
+ for i , v := range value .Children {
507
+ if ! v .Equal (f .Children [i ]) {
508
+ return GetJsonNodeError ("test" , valueAreNotEqual (v , f .Children [i ]))
509
+ }
510
+ }
511
+ case JsonNodeTypeObject :
512
+ if len (f .ChildrenMap ) != len (value .ChildrenMap ) {
513
+ return GetJsonNodeError ("test" , valueAreNotEqual (f .ChildrenMap , value .ChildrenMap ))
514
+ }
515
+ for k , v := range value .ChildrenMap {
516
+ if ! v .Equal (f .ChildrenMap [k ]) {
517
+ return GetJsonNodeError ("test" , valueAreNotEqual (v , f .ChildrenMap [k ]))
518
+ }
519
+ }
520
+ }
521
+ return nil
439
522
}
440
523
441
524
func splitKey (node * JsonNode , path string ) (string , * JsonNode , error ) {
@@ -459,5 +542,5 @@ func keyMustCanBeConvertibleToInt(got interface{}) string {
459
542
}
460
543
461
544
func valueAreNotEqual (one , another interface {}) string {
462
- return fmt .Sprintf ("value are not equal, one is %v, another is %v" , one , another )
545
+ return fmt .Sprintf ("value are not equal, one is %v, another is %v" , one , another )
463
546
}
0 commit comments