@@ -14,12 +14,19 @@ const (
14
14
JSONPointerTildaEncoded = "~0"
15
15
)
16
16
17
+ // JSONObject is a type alias for a map with string keys and values of
18
+ // any type
17
19
type JSONObject = map [string ]any
18
20
21
+ // JSONPointer struct holds the parsed reference tokens of a JSON
22
+ // Pointer
19
23
type JSONPointer struct {
24
+ // Slice of reference tokens derived from the JSON Pointer
20
25
referenceTokens []string
21
26
}
22
27
28
+ // NewJSONPointer creates a new JSONPointer instance from a JSON
29
+ // Pointer string
23
30
func NewJSONPointer (jsonPointer string ) (* JSONPointer , error ) {
24
31
tokens , err := parseJSONPointerString (jsonPointer )
25
32
if err != nil {
@@ -30,6 +37,8 @@ func NewJSONPointer(jsonPointer string) (*JSONPointer, error) {
30
37
}, nil
31
38
}
32
39
40
+ // parseJSONPointerString parses a JSON Pointer string into its
41
+ // reference tokens
33
42
func parseJSONPointerString (jsonPointer string ) ([]string , error ) {
34
43
if jsonPointer == JSONPointerEmptyPointer {
35
44
return []string {}, nil
@@ -40,32 +49,39 @@ func parseJSONPointerString(jsonPointer string) ([]string, error) {
40
49
JSONPointerSeparatorToken ,
41
50
)
42
51
}
52
+ // Split the JSON Pointer into tokens
43
53
tokens := strings .Split (jsonPointer , JSONPointerSeparatorToken )
44
54
return tokens [1 :], nil
45
55
}
46
56
57
+ // GetValue retrieves the value from the JSON document based on the
58
+ // JSON Pointer
47
59
func (jp * JSONPointer ) GetValue (document JSONObject ) (any , error ) {
48
60
if document == nil {
49
61
return nil , fmt .Errorf (
50
62
"jsonpointer: the JSON document provided is nil" ,
51
63
)
52
64
}
53
65
var subDocument any
66
+ // Start with the root of the JSON document
54
67
subDocument = document
55
68
for i , tokenRefEncoded := range jp .referenceTokens {
56
69
tokenRef := decodeJSONPointerReference (tokenRefEncoded )
70
+ // Handle the case where the value is a JSON object
57
71
jsonDoc , ok := subDocument .(JSONObject )
58
72
if ok {
59
73
value , ok := jsonDoc [tokenRef ]
60
74
if ! ok {
61
75
return nil , fmt .Errorf (
62
76
"jsonpointer: the document provided does not have the following reference: %v, %v" ,
63
- tokenRef , i ,
77
+ tokenRef ,
78
+ i ,
64
79
)
65
80
}
66
81
subDocument = value
67
82
continue
68
83
}
84
+ // Handle the case where the value is an Array
69
85
jsonArray , ok := subDocument .([]any )
70
86
if ok {
71
87
index , err := strconv .Atoi (tokenRef )
@@ -85,19 +101,28 @@ func (jp *JSONPointer) GetValue(document JSONObject) (any, error) {
85
101
subDocument = jsonArray [index ]
86
102
continue
87
103
}
88
- return nil , fmt .Errorf ("jsonpointer: the reference is trying to access a single value: %v. Type of subdocument: %T" , tokenRef , subDocument )
104
+ // Handle the case where the value is a single value
105
+ return nil , fmt .Errorf (
106
+ "jsonpointer: the reference is trying to access a single value: %v. Type of subdocument: %T" ,
107
+ tokenRef ,
108
+ subDocument ,
109
+ )
89
110
}
90
111
return subDocument , nil
91
112
}
92
113
114
+ // decodeJSONPointerReference decodes a reference token by replacing
115
+ // escape sequences
93
116
func decodeJSONPointerReference (ref string ) string {
94
- refWithSlash := strings .ReplaceAll (
117
+ // Replace "~1" with "/"
118
+ ref = strings .ReplaceAll (
95
119
ref ,
96
120
JSONPointerSlashEncoded ,
97
121
JSONPointerSeparatorToken ,
98
122
)
123
+ // Replace "~0" with "~"
99
124
return strings .ReplaceAll (
100
- refWithSlash ,
125
+ ref ,
101
126
JSONPointerTildaEncoded ,
102
127
JSONPointerEscapeToken ,
103
128
)
0 commit comments