26
26
package jsonpointer
27
27
28
28
import (
29
+ "encoding/json"
29
30
"errors"
30
31
"fmt"
31
32
"reflect"
@@ -40,6 +41,7 @@ const (
40
41
pointerSeparator = `/`
41
42
42
43
invalidStart = `JSON pointer must be empty or start with a "` + pointerSeparator
44
+ notFound = `Can't find the pointer in the document`
43
45
)
44
46
45
47
var jsonPointableType = reflect .TypeOf (new (JSONPointable )).Elem ()
@@ -361,6 +363,127 @@ func (p *Pointer) String() string {
361
363
return pointerString
362
364
}
363
365
366
+ func (p * Pointer ) Offset (document string ) (int64 , error ) {
367
+ dec := json .NewDecoder (strings .NewReader (document ))
368
+ var offset int64
369
+ for _ , ttk := range p .DecodedTokens () {
370
+ tk , err := dec .Token ()
371
+ if err != nil {
372
+ return 0 , err
373
+ }
374
+ switch tk := tk .(type ) {
375
+ case json.Delim :
376
+ switch tk {
377
+ case '{' :
378
+ offset , err = offsetSingleObject (dec , ttk )
379
+ if err != nil {
380
+ return 0 , err
381
+ }
382
+ case '[' :
383
+ offset , err = offsetSingleArray (dec , ttk )
384
+ if err != nil {
385
+ return 0 , err
386
+ }
387
+ default :
388
+ return 0 , fmt .Errorf ("invalid token %#v" , tk )
389
+ }
390
+ default :
391
+ return 0 , fmt .Errorf ("invalid token %#v" , tk )
392
+ }
393
+ }
394
+ return offset , nil
395
+ }
396
+
397
+ func offsetSingleObject (dec * json.Decoder , decodedToken string ) (int64 , error ) {
398
+ for dec .More () {
399
+ offset := dec .InputOffset ()
400
+ tk , err := dec .Token ()
401
+ if err != nil {
402
+ return 0 , err
403
+ }
404
+ switch tk := tk .(type ) {
405
+ case json.Delim :
406
+ switch tk {
407
+ case '{' :
408
+ if err := drainSingle (dec ); err != nil {
409
+ return 0 , err
410
+ }
411
+ case '[' :
412
+ if err := drainSingle (dec ); err != nil {
413
+ return 0 , err
414
+ }
415
+ }
416
+ case string :
417
+ if tk == decodedToken {
418
+ return offset , nil
419
+ }
420
+ default :
421
+ return 0 , fmt .Errorf ("invalid token %#v" , tk )
422
+ }
423
+ }
424
+ return 0 , fmt .Errorf ("token reference %q not found" , decodedToken )
425
+ }
426
+
427
+ func offsetSingleArray (dec * json.Decoder , decodedToken string ) (int64 , error ) {
428
+ idx , err := strconv .Atoi (decodedToken )
429
+ if err != nil {
430
+ return 0 , fmt .Errorf ("token reference %q is not a number: %v" , decodedToken , err )
431
+ }
432
+ var i int
433
+ for i = 0 ; i < idx && dec .More (); i ++ {
434
+ tk , err := dec .Token ()
435
+ if err != nil {
436
+ return 0 , err
437
+ }
438
+ switch tk := tk .(type ) {
439
+ case json.Delim :
440
+ switch tk {
441
+ case '{' :
442
+ if err := drainSingle (dec ); err != nil {
443
+ return 0 , err
444
+ }
445
+ case '[' :
446
+ if err := drainSingle (dec ); err != nil {
447
+ return 0 , err
448
+ }
449
+ }
450
+ }
451
+ }
452
+ if ! dec .More () {
453
+ return 0 , fmt .Errorf ("token reference %q not found" , decodedToken )
454
+ }
455
+ return dec .InputOffset (), nil
456
+ }
457
+
458
+ // drainSingle drains a single level of object or array.
459
+ // The decoder has to guarantee the begining delim (i.e. '{' or '[') has been consumed.
460
+ func drainSingle (dec * json.Decoder ) error {
461
+ for dec .More () {
462
+ tk , err := dec .Token ()
463
+ if err != nil {
464
+ return err
465
+ }
466
+ switch tk := tk .(type ) {
467
+ case json.Delim :
468
+ switch tk {
469
+ case '{' :
470
+ if err := drainSingle (dec ); err != nil {
471
+ return err
472
+ }
473
+ case '[' :
474
+ if err := drainSingle (dec ); err != nil {
475
+ return err
476
+ }
477
+ }
478
+ }
479
+ }
480
+ // Consumes the ending delim
481
+ if _ , err := dec .Token (); err != nil {
482
+ return err
483
+ }
484
+ return nil
485
+ }
486
+
364
487
// Specific JSON pointer encoding here
365
488
// ~0 => ~
366
489
// ~1 => /
0 commit comments