-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsonpointer.go
83 lines (70 loc) · 1.44 KB
/
jsonpointer.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
package rfc6902
import (
"fmt"
"net/url"
"strings"
)
type jsonptr []reftoken
// return the escaped path (see section 3. Syntax)
func (j jsonptr) remainder(i int) (s string) {
for _, ref := range j[i:] {
s += "/" + string(ref)
}
s = s[1:]
return
}
func (j jsonptr) String() (s string) {
for _, ref := range j {
s += "/" + ref.token()
}
return
}
func (j jsonptr) element() string {
return j[len(j)-1].token()
}
type reftoken string
func (r reftoken) token() string {
return decode(string(r))
}
// decode according to Section 3. Syntax
func decode(in string) string {
in = strings.Replace(in, "~1", "/", -1)
return strings.Replace(in, "~0", "~", -1)
}
func newRefToken(in string) reftoken {
if len(in) <= 0 {
panic("jsonptr cannot be formed from zero length string")
}
if in[0] != '/' {
panic("jsonptr must contain a leading '/'")
}
return reftoken(in[1:])
}
func newJSONPointer(path string) (head jsonptr, err error) {
if len(path) > 0 && path[0] == '#' {
path, err = url.QueryUnescape(path[1:])
if err != nil {
return nil, err
}
}
s := path
for len(s) > 0 {
if s[0] == '/' {
if len(s) == 1 {
head = append(head, newRefToken(s))
break
}
next := strings.Index(s[1:], "/")
if next == -1 {
head = append(head, newRefToken(s))
break
}
next += 1
head = append(head, newRefToken(s[:next]))
s = s[next:]
} else {
panic(fmt.Sprintf("field must start with '/': %q", s))
}
}
return
}