Repository navigation
Expand file tree
/
Copy pathdiff.go
More file actions
126 lines (109 loc) · 2.53 KB
/
Copy pathdiff.go
File metadata and controls
126 lines (109 loc) · 2.53 KB
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
package qjson
import (
"fmt"
"strconv"
"strings"
)
type DiffType int
const undefined = "undefined"
const (
DiffOfType DiffType = iota
DiffOfValue
)
func (t DiffType) String() string {
switch t {
case DiffOfType:
return "Type"
case DiffOfValue:
return "Value"
default:
return ""
}
}
func Diff(t1, t2 *JSONTree) DiffItems {
d := &differ{}
d.diffNode(t1.Root, t2.Root, "")
return d.diffList
}
type DiffItem struct {
Type DiffType
Path string
Left, Right string
}
type DiffItems []DiffItem
func (items DiffItems) Exist() bool { return len(items) > 0 }
func (items DiffItems) String() string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("Total %v diff\n", len(items)))
for _, item := range items {
sb.WriteString(item.String() + "\n")
}
return sb.String()
}
func (item DiffItem) String() string {
return fmt.Sprintf("DiffOf%v Path: %v Left:%v Right:%v", item.Type.String(), item.Path, item.Left, item.Right)
}
type differ struct {
diffList []DiffItem
}
func (d *differ) diffNode(n1, n2 *Node, prefix string) {
if n1.Type != n2.Type {
d.addDiff(DiffOfType, prefix, n1, n2)
return
}
switch n1.Type {
case String, Bool, Integer, Float:
if n1.Value != n2.Value {
d.addDiff(DiffOfValue, prefix, n1, n2)
}
case Object:
d.diffObject(n1, n2, prefix)
case Array:
d.diffArray(n1, n2, prefix)
}
}
func (d *differ) diffArray(n1, n2 *Node, prefix string) {
if len(n1.ArrayValues) != len(n2.ArrayValues) {
d.addDiff(DiffOfValue, prefix, n1, n2)
return
}
for i, item := range n1.ArrayValues {
d.diffNode(item, n2.ArrayValues[i], d.appendPath(prefix, strconv.Itoa(i)))
}
}
func (d *differ) diffObject(n1, n2 *Node, prefix string) {
left, right := n1.AsMap(), n2.AsMap()
for k, v := range left {
v2, ok := right[k]
if !ok {
d.addDiff(DiffOfValue, d.appendPath(prefix, k), v, nil)
continue
}
d.diffNode(v, v2, d.appendPath(prefix, k))
delete(right, k)
}
for k, v := range right {
v2, ok := left[k]
if !ok {
d.addDiff(DiffOfValue, d.appendPath(prefix, k), nil, v)
continue
}
d.diffNode(v, v2, d.appendPath(prefix, k))
}
}
func (d *differ) appendPath(prefix string, suffix ...string) string {
if len(suffix) > 0 {
return prefix + "." + strings.Join(suffix, ".")
}
return prefix
}
func (d *differ) addDiff(t DiffType, prefix string, ln, rn *Node) {
lv, rv := undefined, undefined
if ln != nil {
lv = ln.AsJSON()
}
if rn != nil {
rv = rn.AsJSON()
}
d.diffList = append(d.diffList, DiffItem{Type: t, Path: strings.TrimPrefix(prefix, "."), Left: lv, Right: rv})
}