/
matcher.go
142 lines (100 loc) · 3.29 KB
/
matcher.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
package json
import (
"bytes"
"regexp"
"strings"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
)
func MatchNull(json []byte, path string) error {
if bytes.Equal(bytes.TrimSpace(json), []byte("null")) && (path == "" || path == ".") {
return nil
}
path = revertLegacySyntax(path)
result := gjson.GetBytes(json, path)
if result.Exists() && !result.IsArray() && !result.IsObject() && result.Value() == nil {
return nil
}
return errors.Errorf("Match error: Expected null got '%s' JSON: %s", result.String(), string(json))
}
func KeyIsMissing(json []byte, path string) error {
if bytes.Equal(bytes.TrimSpace(json), []byte("null")) && (path == "" || path == ".") {
return nil
}
path = revertLegacySyntax(path)
result := gjson.GetBytes(json, path)
if !result.Exists() {
return nil
}
return errors.Errorf("Match error: Expected null got '%s' JSON: %s", result.String(), string(json))
}
func KeyIsPresent(json []byte, path string) error {
if bytes.Equal(bytes.TrimSpace(json), []byte("null")) && (path == "" || path == ".") {
return nil
}
path = revertLegacySyntax(path)
result := gjson.GetBytes(json, path)
if result.Exists() {
return nil
}
return errors.Errorf("Match error: Expected path to be present, missing path: %s", path)
}
func Match(json []byte, path string, pattern string) error {
re, err := regexp.Compile(pattern)
if err != nil {
return errors.Wrap(err, "Failed to compile regexp")
}
path = revertLegacySyntax(path)
result := gjson.GetBytes(json, path)
if !re.MatchString(result.String()) {
return errors.Errorf("Match error: Values mismatch, pattern: '%s' value: '%s' JSON: %s", pattern, result.String(), string(json))
}
return nil
}
func ArrayLen(json []byte, path string, length int) error {
path = revertLegacySyntax(path)
res := gjson.GetBytes(json, path)
if !res.IsArray() {
return errors.Errorf("Match error: Expected an array got: %s, JSON: %s", res.String(), string(json))
}
if len(res.Array()) != length {
return errors.Errorf("Match error: Expected an array of length: %d got: %d JSON: %s", length, len(res.Array()), string(json))
}
return nil
}
func Read(json []byte, path string) (result string, err error) {
path = revertLegacySyntax(path)
res := gjson.GetBytes(json, path)
if !res.Exists() || res.IsObject() || res.IsArray() {
return "", errors.Errorf("Match error: Expected a scalar got '%s' JSON: %s", res.String(), string(json))
}
return res.String(), nil
}
func ReadStringArr(json []byte, path string) (result []string, err error) {
path = revertLegacySyntax(path)
res := gjson.GetBytes(json, path)
if !res.IsArray() {
return []string{}, errors.Errorf("Match error: Expected an array got: %s", res.String())
}
for _, v := range res.Array() {
stringValue := v.String()
if !isScalar(v) {
return []string{}, errors.Errorf("Match error: Expected a scalar got: %s", stringValue)
}
result = append(result, stringValue)
}
return result, nil
}
func isScalar(v gjson.Result) bool {
return !v.IsArray() && !v.IsObject()
}
func revertLegacySyntax(path string) string {
// Remove brackets earlier they were used for array indexing
bracketRegexp := regexp.MustCompile(`\.?\[(\d+)]`)
path = bracketRegexp.ReplaceAllString(path, ".$1")
path = strings.TrimPrefix(path, ".")
if path == "" {
path = "@this"
}
return path
}