@@ -14,12 +14,19 @@ const (
1414 JSONPointerTildaEncoded = "~0"
1515)
1616
17+ // JSONObject is a type alias for a map with string keys and values of
18+ // any type
1719type JSONObject = map [string ]any
1820
21+ // JSONPointer struct holds the parsed reference tokens of a JSON
22+ // Pointer
1923type JSONPointer struct {
24+ // Slice of reference tokens derived from the JSON Pointer
2025 referenceTokens []string
2126}
2227
28+ // NewJSONPointer creates a new JSONPointer instance from a JSON
29+ // Pointer string
2330func NewJSONPointer (jsonPointer string ) (* JSONPointer , error ) {
2431 tokens , err := parseJSONPointerString (jsonPointer )
2532 if err != nil {
@@ -30,6 +37,8 @@ func NewJSONPointer(jsonPointer string) (*JSONPointer, error) {
3037 }, nil
3138}
3239
40+ // parseJSONPointerString parses a JSON Pointer string into its
41+ // reference tokens
3342func parseJSONPointerString (jsonPointer string ) ([]string , error ) {
3443 if jsonPointer == JSONPointerEmptyPointer {
3544 return []string {}, nil
@@ -40,32 +49,39 @@ func parseJSONPointerString(jsonPointer string) ([]string, error) {
4049 JSONPointerSeparatorToken ,
4150 )
4251 }
52+ // Split the JSON Pointer into tokens
4353 tokens := strings .Split (jsonPointer , JSONPointerSeparatorToken )
4454 return tokens [1 :], nil
4555}
4656
57+ // GetValue retrieves the value from the JSON document based on the
58+ // JSON Pointer
4759func (jp * JSONPointer ) GetValue (document JSONObject ) (any , error ) {
4860 if document == nil {
4961 return nil , fmt .Errorf (
5062 "jsonpointer: the JSON document provided is nil" ,
5163 )
5264 }
5365 var subDocument any
66+ // Start with the root of the JSON document
5467 subDocument = document
5568 for i , tokenRefEncoded := range jp .referenceTokens {
5669 tokenRef := decodeJSONPointerReference (tokenRefEncoded )
70+ // Handle the case where the value is a JSON object
5771 jsonDoc , ok := subDocument .(JSONObject )
5872 if ok {
5973 value , ok := jsonDoc [tokenRef ]
6074 if ! ok {
6175 return nil , fmt .Errorf (
6276 "jsonpointer: the document provided does not have the following reference: %v, %v" ,
63- tokenRef , i ,
77+ tokenRef ,
78+ i ,
6479 )
6580 }
6681 subDocument = value
6782 continue
6883 }
84+ // Handle the case where the value is an Array
6985 jsonArray , ok := subDocument .([]any )
7086 if ok {
7187 index , err := strconv .Atoi (tokenRef )
@@ -85,19 +101,28 @@ func (jp *JSONPointer) GetValue(document JSONObject) (any, error) {
85101 subDocument = jsonArray [index ]
86102 continue
87103 }
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+ )
89110 }
90111 return subDocument , nil
91112}
92113
114+ // decodeJSONPointerReference decodes a reference token by replacing
115+ // escape sequences
93116func decodeJSONPointerReference (ref string ) string {
94- refWithSlash := strings .ReplaceAll (
117+ // Replace "~1" with "/"
118+ ref = strings .ReplaceAll (
95119 ref ,
96120 JSONPointerSlashEncoded ,
97121 JSONPointerSeparatorToken ,
98122 )
123+ // Replace "~0" with "~"
99124 return strings .ReplaceAll (
100- refWithSlash ,
125+ ref ,
101126 JSONPointerTildaEncoded ,
102127 JSONPointerEscapeToken ,
103128 )
0 commit comments