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
219
320import (
21+ "bytes"
422 "fmt"
23+ "regexp"
524 "strconv"
625 "strings"
726)
827
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+
971type JsonNodeType uint8
1072
1173const (
@@ -23,15 +85,15 @@ const (
2385)
2486
2587func (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 ""
3597}
3698
3799// JsonNode 以树的形式组织 Json 中的每一项数据。
@@ -51,13 +113,23 @@ func (jt JsonNodeType) String() string {
51113// 一个 Json 字节数组可以使用 Unmarshal 反序列化为 JsonNode 对象,
52114// JsonNode 对象也可以使用 Marshal 序列化为 Json 字节数组
53115type 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+ }
61133}
62134
63135func NewObjectNode (key string , childrenMap map [string ]* JsonNode , level int ) * JsonNode {
@@ -134,6 +206,17 @@ func (jn *JsonNode) ADD(key interface{}, value *JsonNode) error {
134206 return nil
135207}
136208
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+
137220// AddPath 为 node 的 path 路径处的对象添加一个子节点
138221// path 路径表示的是子节点加入后的路径, 以 "/" 开头
139222func AddPath (node * JsonNode , path string , value * JsonNode ) error {
@@ -196,7 +279,7 @@ func (jn *JsonNode) Equal(patch *JsonNode) bool {
196279func (jn * JsonNode ) find (paths []string ) (* JsonNode , bool ) {
197280 root := jn
198281 for _ , key := range paths {
199- key = keyRestore (key )
282+ key = KeyRestore (key )
200283 switch root .Type {
201284 case JsonNodeTypeObject :
202285 r , ok := root .ChildrenMap [key ]
@@ -400,42 +483,42 @@ func CopyPath(node *JsonNode, from, path string) error {
400483}
401484
402485func 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
439522}
440523
441524func splitKey (node * JsonNode , path string ) (string , * JsonNode , error ) {
@@ -459,5 +542,5 @@ func keyMustCanBeConvertibleToInt(got interface{}) string {
459542}
460543
461544func 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 )
463546}
0 commit comments