Package jsondata ::
Module JSONPointer
|
|
1
2 """Provides classes for the JSONPointer definition in accordance to RFC6901.
3
4 The provided class JSONPointer internally stores and applies pointer data
5 as a list of keys and indexes with the additional cooperative caching of
6 the pointed in-memory node reference for fast access on data provided by
7 the packages 'json' and 'jsonschema'. Requests for the string representation
8 are transformed into a pointer path in accordance to RFC6901.
9
10 The JSONPointer class combines fast in-memory operations and pointer
11 arithmetics with standards compliant path strings at the API.
12
13 The JSONPointer class by itself is focused on the path pointer itself, though
14 the provided operations do not touch the content value. The pointer provides
15 the hook where the value has to be inserted.
16 """
17 __author__ = 'Arno-Can Uestuensoez'
18 __maintainer__ = 'Arno-Can Uestuensoez'
19 __license__ = "Artistic-License-2.0 + Forced-Fairplay-Constraints"
20 __copyright__ = "Copyright (C) 2015-2016 Arno-Can Uestuensoez @Ingenieurbuero Arno-Can Uestuensoez"
21 __version__ = '0.2.14'
22 __uuid__='63b597d6-4ada-4880-9f99-f5e0961351fb'
23
24 import sys
25
26 version = '{0}.{1}'.format(*sys.version_info[:2])
27 if not version in ('2.6','2.7',):
28 raise Exception("Requires Python-2.6.* or higher")
29
30
31
32 from types import StringTypes,NoneType
33 import re
34 try:
35 from urllib import unquote
36 from itertools import izip
37 except ImportError:
38 from urllib.parse import unquote
39 izip = zip
40
41
42
43 _interactive = False
44
45
46 NOTATION_JSON = 0
47 """JSON notation in accordance to RFC7159
48 """
49
50 NOTATION_HTTP_FRAGMENT = 1
51 """JSON notation in accordance to RFC7159 with RFC3986.
52 """
53
54 VALID_NODE_TYPE = (dict, list, str, unicode, int, float, bool, NoneType,)
55 """Valid types of in-memory JSON node types."""
56
57
58 CHARSET_UTF = 0
59 """Unicode."""
60
61 CHARSET_STR = 1
62 """Python string."""
63
66
68 """Represents exactly one JSONPointer in compliance with IETF RFC6901.
69 This pointer could be processed by extension, reduction, and general modification
70 with support of provided methods and path arithmetic operators.
71
72 The JSONPointer is provided at the API as a utf(-8) string in accordance
73 to RFC6901, including RFC3869.
74
75 For enhancement of the processing performance by the underlying packages
76 'json' and 'jsonschema', the pointer is stored and applied in two variants.
77
78 * self.raw: Raw input of the pointer string for the logical API.
79
80 * self.ptr: Split elements of the pointer path within a list of keys,
81 for the programming interface.
82
83 The attribute 'self.ptr' contains the path elements in a
84 'list'::
85
86 ptrlist := (<EMPTY>|plist)
87 <EMPTY> := "empty list, represents the whole document"
88 plist := pkey [, plist ]
89 pkey := (''|int|keyname)
90 '' := "the empty string is a valid key too"
91 int := "integer index of an array item, just digits"
92 keyname := "the valid name of an object/property entry"
93
94 The JSONPointer::
95
96 "/address/0/streetName"
97
98 is represented as::
99
100 ['address', 0, 'streetName' ]
101
102
103 The methods and operators are handling the pointer itself, the values
104 referenced by the pointer are not modified.
105
106 The methods of this class support for multiple input format of
107 the JSONPointer. The parameter 'x' in the operations is defined as a
108 valid JSONPointer fragment. A pointer fragment is a part of a pointer,
109 which could be the complete pointer itself - the all-fragment.
110
111 The syntax element could be one of::
112
113 'str': A string i accordance to RFC6901. Strings are represented
114 internally as unicode utf-8.
115
116 Here either the input parameter 'x' is split into
117 a list, or in case of combining operations, the self.ptr
118 attribute is 'joined' to be used for the method.
119
120 'int': A numeric value in case of an array index. This value
121 is internally handled for the string representation as a
122 unicode utf-8, whereas for the addressing of memory
123 objects the numeric integer value is stored and applied.
124
125 'JSONPointer': The attributes of the input object are used
126 with it's peers.
127
128 'list': Expects a path list containing:
129 - JSON object names
130 Names of the json objects.
131 - array indexes
132 Numeric index for arrays.
133 - JSONPointer
134 A JSONPointer object, the path is resolved as a section
135 of overall path.
136
137 The self.ptr attribute is applied for operations.
138
139 The node reference is cached by the 'get_node' and 'get_node_or_value'
140 method, thus could be accessed by 'self.node', but is not monitored
141 to be valid. Another call of the method reloads the cache by evaluating
142 the pointer value on the document again.
143
144 The provided value is internally stored as a raw input value, and a list
145 of keys and indexes for access to in-memory data as provided by the
146 packages 'json' and 'jsonschema'. Requests for the string representation
147 are transformed into a pointer path in accordance to RFC6901. This provides
148 for fast access in case of pointer arithmetics, while providing standards
149 conform path strings at the interface.
150 """
151 VALID_INDEX = re.compile('0|[1-9][0-9]*$')
152 """Regular expression for valid numerical index."""
153
154 - def __init__(self,ptr,replace=True,**kargs):
155 """ Converts and stores a JSONPointer as a list.
156
157 Processes the ABNF of a JSON Pointer from RFC6901.
158
159 Args:
160 ptr: A JSONPointer to be represented by this object. The
161 supported formats are:
162 'str': A string i accordance to RFC6901
163 JSONPointer: A valid object, will be copied
164 into this, see 'deep'.
165 'list': expects a path list, where each item
166 is processed for escape and unquote.
167 replace: Replaces masked characters.
168 **kargs:
169 deep: Applies for copy operations on structured data
170 'deep' when 'True', else 'swallow' only, which is
171 just a link to the data structure. Flat data types
172 are copied by value in any case.
173 node: Force to set the pointed node in the internal cache.
174 debug: Enable debugging.
175
176 Returns:
177 When successful returns 'True', else returns either 'False', or
178 raises an exception.
179 Success is the complete addition only, thus one failure returns
180 False.
181
182 Raises:
183 JSONPointerException:
184
185 """
186 self.debug = kargs.get('debug',False)
187 self.node = kargs.get('node',None)
188 self.deep = deep = kargs.get('deep',False)
189 if ptr and type(ptr) in (str,unicode) and ptr[0] is '#':
190 ptr = ptr[1:]
191
192 if type(ptr) in (int,float):
193 ptr=u'/'+unicode(ptr)
194
195 if ptr == '':
196 self.raw = ''
197 self = []
198 return None
199
200 elif ptr == '/':
201 self.raw = ptr
202 self.append('')
203 return None
204
205 elif isinstance(ptr, StringTypes):
206 if ptr[0] == '/':
207 self.extend(ptr[1:].split('/'))
208 else:
209 self.extend(ptr.split('/'))
210 ptr = u'/'+ptr
211
212 if deep:
213 self.raw = ptr[:]
214 else:
215 self.raw = ptr
216
217 elif isinstance(ptr, JSONPointer):
218 if deep:
219 self.raw = ptr.raw[:]
220 self.extend(ptr.copy_path())
221 else:
222 self.raw = ptr.raw
223 self.extend(ptr)
224
225 elif type(ptr) is list:
226 def presolv(p0):
227 if isinstance(p0, JSONPointer):
228 return p0.ptr
229 elif p0 in ('', '/'):
230 return p0
231 elif type(p0) in (str,unicode):
232 return p0
233 elif type(p0) in (int,float):
234 return str(p0)
235 else:
236 raise JSONPointerException("Invalid nodepart:"+str(p0))
237 return p0
238 if deep:
239 self.extend(map(lambda s:s[:],ptr))
240 else:
241 self.extend(map(presolv,ptr))
242 self.raw = '/'+'/'.join(self)
243 else:
244 if not ptr:
245 self.raw = None
246 return None
247 raise JSONPointerException("Pointer type not supported:",type(ptr))
248
249 if replace:
250 x = map(lambda p: type(p) in (str,unicode) and unquote(p).replace('~1', '/').replace('~0', '~') or p,self)
251 del self[:]
252 self.extend(x)
253
254
255 def checkint(ix):
256 if type(ix) in (str,unicode,) and ix.isdigit():
257 return int(ix)
258 return ix
259 x = map(checkint,self)
260 del self[:]
261 self.extend(x)
262
264 """Appends a Pointer to self.
265
266 Args:
267 x: A valid JSONPointer fragment.
268
269 Returns:
270 A new object of JSONPointer
271
272 Raises:
273 JSONPointerException:
274
275 """
276 ret = JSONPointer(self)
277 if type(x) in (str,unicode) and x[0] is '#':
278 x = x[1:]
279
280 if x == '':
281 raise JSONPointerException("Cannot add the whole document")
282 elif x == u'/':
283 ret.raw += x
284 ret.append('')
285
286 elif isinstance(x, JSONPointer):
287 ret.raw += x.raw
288 ret.extend(x)
289 elif type(x) == list:
290 ret.raw += u'/'+u'/'.join(x)
291 ret.extend(x)
292 elif type(x) in (str,unicode):
293 if x[0] == u'/':
294 ret.extend(x[1:].split('/'))
295 ret.raw += x
296 else:
297 ret.extend(x.split('/'))
298 ret.raw += u'/'+x
299 elif type(x) is int:
300 ret.append(x)
301 ret.raw += u'/'+unicode(x)
302 elif type(x) is NoneType:
303 return ret
304
305 else:
306 raise JSONPointerException()
307 return ret
308
310 """Evaluates the pointed value from the document.
311
312 Args:
313 x: A valid JSON document.
314
315 Returns:
316 The pointed value, or None.
317
318 Raises:
319 JSONPointerException
320 """
321 return self.get_node_or_value(x)
322
324 """Compares this pointer with x.
325
326 Args:
327 x: A valid Pointer.
328
329 Returns:
330 True or False
331
332 Raises:
333 JSONPointerException
334 """
335 s = u'/'+u'/'.join(map(unicode,self))
336
337 if isinstance(x, JSONPointer):
338 return s == x.get_pointer()
339 elif type(x) == list:
340
341 return s == JSONPointer(x).get_pointer()
342 elif type(x) in (str,unicode):
343 return s == unicode(x)
344 elif type(x) in (int):
345 return s == u'/'+unicode(x)
346 elif type(x) is NoneType:
347 return False
348
349 else:
350 raise JSONPointerException()
351 return False
352
354 """Checks containment(>=) of another pointer within this.
355
356 The weight of contained entries is the criteria, though
357 the shorter is the bigger. This is true only in case of
358 a containment relation.
359
360 The number of equal path pointer items is compared.
361
362 Args:
363 x: A valid Pointer.
364
365 Returns:
366 True or False
367
368 Raises:
369 JSONPointerException:
370
371 """
372 s = u'/'+u'/'.join(map(unicode,self))
373
374 if isinstance(x, JSONPointer):
375 px = x.get_pointer()
376 elif type(x) == list:
377 px = u"/"+'/'.join(map(unicode,x))
378 elif type(x) in (str,unicode):
379 px = unicode(x)
380 elif type(x) in (int):
381 px = u'/'+unicode(x)
382 elif type(x) is NoneType:
383 return True
384
385 else:
386 raise JSONPointerException()
387
388 if s > px:
389 return False
390 if unicode(px).startswith(unicode(s)):
391 return True
392 else:
393 return False
394
396 """Checks containment(>) of another pointer or object within this.
397
398 The number of equal items is compared.
399
400 Args:
401 x: A valid Pointer.
402
403 Returns:
404 True or False
405
406 Raises:
407 JSONPointerException:
408 """
409 s = u'/'+u'/'.join(map(unicode,self))
410
411 if isinstance(x, JSONPointer):
412 px = x.get_pointer()
413 elif type(x) == list:
414 px = u"/"+u'/'.join(map(unicode,x))
415 elif type(x) in (str,unicode):
416 px = unicode(x)
417 elif type(x) in (int):
418 px = u'/'+unicode(x)
419 elif type(x) is NoneType:
420 return True
421
422 else:
423 raise JSONPointerException()
424
425 if s >= px:
426 return False
427 if unicode(px).startswith(unicode(s)):
428 return True
429 else:
430 return False
431
433 """Add in place x to self, appends a path.
434
435 Args:
436 x: A valid Pointer.
437
438 Returns:
439 'self' with updated pointer attributes
440
441 Raises:
442 JSONPointerException:
443 """
444 if type(x) == list:
445 self.raw += unicode('/'+'/'.join(x))
446 self.extend(x)
447 elif isinstance(x, JSONPointer):
448 if x.raw[0] != u'/':
449 self.raw += u'/'+x.raw
450 else:
451 self.raw = x.raw
452 self.extend(x)
453 elif type(x) is int:
454 self.append(unicode(x))
455 self.raw += u'/'+unicode(x)
456 elif x == '':
457 raise JSONPointerException("Cannot add the whole document")
458 elif x == u'/':
459 self.raw += x
460 self.append('')
461 elif type(x) in (str,unicode):
462 if x[0] == u'/':
463 self.extend(x[1:].split('/'))
464 self.raw += x
465 else:
466 self.extend(x.split('/'))
467 self.raw += u'/'+x
468 elif type(x) is NoneType:
469 return self
470
471 else:
472 raise JSONPointerException()
473 return self
474
476 """Checks containment(<=) of this pointer within another.
477
478 The number of equal items is compared.
479
480 Args:
481 x: A valid Pointer.
482
483 Returns:
484 True or False
485
486 Raises:
487 JSONPointerException:
488 """
489 s = u'/'+u'/'.join(map(unicode,self))
490
491 if isinstance(x, JSONPointer):
492 px = x.get_pointer()
493 elif type(x) == list:
494 px = u"/"+u'/'.join(map(unicode,x))
495 elif type(x) in (str,unicode):
496 px = unicode(x)
497 elif type(x) in (int):
498 px = u'/'+unicode(x)
499 elif type(x) is NoneType:
500 return False
501
502 else:
503 raise JSONPointerException()
504
505 if s < px:
506 return False
507 if unicode(s).startswith(unicode(px)):
508 return True
509
511 """Checks containment(<) of this pointer within another.
512
513 The number of equal items is compared.
514
515 Args:
516 x: A valid Pointer.
517
518 Returns:
519 True or False
520
521 Raises:
522 JSONPointerException:
523 """
524 s = u'/'+u'/'.join(map(unicode,self))
525
526 if isinstance(x, JSONPointer):
527 px = x.get_pointer()
528 elif type(x) == list:
529 px = u"/"+u'/'.join(map(unicode,x))
530 elif type(x) in (str,unicode):
531 px = unicode(x)
532 elif type(x) in (int):
533 px = u'/'+unicode(x)
534 elif type(x) is NoneType:
535 return False
536
537 else:
538 raise JSONPointerException()
539
540 if s <= px:
541 return False
542 if unicode(s).startswith(unicode(px)):
543 return True
544
546 """Compares this pointer with x.
547
548 Args:
549 x: A valid Pointer.
550
551 Returns:
552 True or False
553
554 Raises:
555 JSONPointerException
556 """
557 return not self.__eq__(x)
558
560 """Adds itself as the right-side-argument to the left.
561
562 This method appends 'self' to a path fragment on the left.
563 Therefore it adds the path separator on it's left side only.
564 The left side path fragment has to maintain to be in
565 accordance to RFC6901 by itself.
566
567 Once 'self' is added to the left side, it terminates it's
568 life cycle. Thus another simultaneous add operation is
569 handled by the resulting other element.
570
571 Args:
572 x: A valid Pointer.
573
574 Returns:
575 The updated input of type 'x' as 'x+S(x)'
576
577 Raises:
578 JSONPointerException:
579 """
580 if x == '':
581 return u'/'+u'/'.join(map(unicode,self))
582 elif x == u'/':
583 return x+u'/'+u'/'.join(map(unicode,self))
584 elif type(x) is int:
585 return u'/'+unicode(x)+u'/'+u'/'.join(map(unicode,self))
586 elif type(x) in (str,unicode):
587 return x+u'/'+u'/'.join(map(unicode,self))
588 elif type(x) == list:
589 return x.extend(self)
590 else:
591 raise JSONPointerException()
592 return x
593
595 """Returns the attribute self.raw, which is the raw input JSONPointer.
596 """
597 return unicode(super(JSONPointer,self).__repr__())
598
600 """Returns the string for the processed path.
601 """
602 ret = self.get_pointer()
603 if ret == '':
604 return "''"
605 return ret
606
607
608
609
610
612 """Checks the existance of the corresponding node within the JSON document.
613
614 Args:
615 jsondata: A valid JSON data node.
616 parent: Return the parent node of the pointed value.
617
618 Returns:
619 True or False
620
621 Raises:
622 JSONPointerException:
623 forwarded from json
624 """
625 if self == []:
626 return jsondata
627 if self == ['']:
628 return jsondata['']
629
630 if type(jsondata) not in VALID_NODE_TYPE:
631
632 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
633
634 if parent:
635 for x in self.ptr[:-1]:
636 jsondata=jsondata.get(x,False)
637 if not jsondata:
638 return False
639 else:
640 for x in self.ptr:
641 jsondata=jsondata.get(x,False)
642 if not jsondata:
643 return False
644
645 if type(jsondata) not in VALID_NODE_TYPE:
646
647 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
648 self.node = jsondata
649 return True
650
652 """Returns a deep copy of the objects pointer path list.
653
654 Args:
655 parent: The parent node of the pointer path.
656
657 Returns:
658 A copy of the path list.
659
660 Raises:
661 none
662 """
663 if self == []:
664 return []
665 if self == ['']:
666 return ['']
667
668 if parent:
669 return map(lambda s:s[:],self[:-1])
670 else:
671 return map(lambda s:s[:],self[:])
672
673 - def get_node(self,jsondata,parent=False):
674 """Gets the corresponding node reference for a JSON container type.
675
676 This method gets nodes of container types. Container
677 types of JSON are 'array' a.k.a. in Python 'list',
678 and 'objects' a.k.a. in Python 'dict'.
679
680 Due to the special case of RFC6902 'append' by the array
681 index '-' in combination of the add rules a special
682 exception-treatment is required, for details refer to RFC6902.
683
684 The 'get_node' method therefore returns only an existing
685 node of a of valid non-ambiguous path pointer. This
686 excludes pointers containing the symbolic index '-' for
687 an array component.
688
689 See also related methods:
690
691 get_node_and_child: For Python access to a child node
692 within a container by the container itself, and the
693 item key.
694 get_node_exist: For the application of partial valid
695 pointer paths of new branches.
696 get_node_or_value: For any type of pointed item, either
697 a node, or a value.
698
699 Args:
700 jsondata: A valid JSON data node.
701 parent: Return the parent node of the pointed value.
702 When parent is selected, the pointed child node
703 is not verified.
704
705 Returns:
706 The node reference.
707
708 Raises:
709 JSONPointerException:
710 forwarded from json
711 """
712 if self == []:
713 return jsondata
714 if len(self) == 1 and self[0] == '':
715 return jsondata[0]
716
717 if type(jsondata) not in (dict, list):
718
719 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
720
721 try:
722 if parent:
723 for x in self[:-1]:
724 jsondata=jsondata[x]
725 else:
726 for x in self:
727 jsondata=jsondata[x]
728 except Exception as e:
729 raise JSONPointerException("Requires existing Node("+str(self.index(x))+"):"+str(x)+" of "+str(self)+":"+str(e))
730 if type(jsondata) not in (dict, list):
731
732 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
733 self.node = jsondata
734 return jsondata
735
737 """Returns a tuple containing the parent node and the child.
738
739 Args:
740 jsondata: A valid JSON data node.
741
742 Returns:
743 The the tuple:
744 (n,c): n: Node reference to parent container.
745 c: Key for the child entry, either an
746 index 'int', or a key ('str', 'unicode').
747 Raises:
748 JSONPointerException:
749 forwarded from json
750 """
751 n = self.get_node(jsondata,True)
752 return n,self[-1]
753
755 """Gets the corresponding node reference or the JSON value of a leaf.
756
757 Relies on the standard package 'json' by 'Bob Ippolito <bob@redivi.com>'.
758 This package supports in the current version the following types:
759
760 +---------------+-------------------+
761 | JSON | Python |
762 +===============+===================+
763 | object | dict |
764 +---------------+-------------------+
765 | array | list |
766 +---------------+-------------------+
767 | string | unicode |
768 +---------------+-------------------+
769 | number (int) | int, long |
770 +---------------+-------------------+
771 | number (real) | float |
772 +---------------+-------------------+
773 | true | True |
774 +---------------+-------------------+
775 | false | False |
776 +---------------+-------------------+
777 | null | None |
778 +---------------+-------------------+
779
780 It also understands ``NaN``, ``Infinity``, and
781 ``-Infinity`` as their corresponding ``float``
782 values, which is outside the JSON spec.
783
784
785 The supported standard value types for Python
786 of get_node_or_value() are mapped automatically
787 as depicted in the following table. Additional
788 bindings may be implemented by sub-classing.
789
790 +------------------------+-------------------+
791 | JSONPointer(jsondata) | Python-valtype |
792 +========================+===================+
793 | object (dict) | dict |
794 +------------------------+-------------------+
795 | array (list) | list |
796 +------------------------+-------------------+
797 | array (tuple) | list |
798 +------------------------+-------------------+
799 | string | unicode |
800 +------------------------+-------------------+
801 | number (int) | int |
802 +------------------------+-------------------+
803 | number (long) | long |
804 +------------------------+-------------------+
805 | number (float) | float |
806 +------------------------+-------------------+
807 | *number (double) | float |
808 +------------------------+-------------------+
809 | number (octal) | int |
810 +------------------------+-------------------+
811 | number (hex) | int |
812 +------------------------+-------------------+
813 | number (binary) | int |
814 +------------------------+-------------------+
815 | number (complex) | - (custom) |
816 +------------------------+-------------------+
817 | true | True |
818 +------------------------+-------------------+
819 | false | False |
820 +------------------------+-------------------+
821 | null | None |
822 +------------------------+-------------------+
823
824 The mappings in detail are:
825
826 * object(dict) => dict:
827 {a:b} - native Python dictionary
828
829 * array(list) => list:
830 [a,b] - native Python list
831
832 * (*)array(tuple) => list:
833 (a,b) - native Python list
834
835 * string(str) => unicode"
836 "abc" - native Python unicode string UTF-8
837
838 * number(int) => int:
839 1234, −24, 0 - Integers (unlimited precision)
840
841 * number(long) => int:
842 1234, −24, 0 - Integers (unlimited precision)
843
844 * number(float) => float:
845 1.23, 3.14e-10, 4E210, 4.0e+210, 1., .1 -
846 Floating-point (normally implemented as C doubles in CPython)
847
848 * (*)number(double) => float:
849 1.23, 3.14e-10, 4E210, 4.0e+210, 1., .1 -
850 Floating-point (normally implemented as C doubles in CPython)
851
852 * number(octal) => int:
853 0o177 -
854 Octal, hex, and binary literals for integers2
855
856 * number(hex) => int:
857 0x9ff - Octal, hex, and binary literals for integers2
858
859 * number(binary) => int:
860 0b1111 - Octal, hex, and binary literals for integers2
861
862 * number(complex) => <not-supported>(requires custom):
863 3+4j, 3.0+4.0j, 3J - Complex numbers
864
865 * true(True) => boolean(True):
866 True - native Python boolean
867
868 * false(False) => boolean(False):
869 False - native Python boolean
870
871 * null(None) => NoneType(None):
872 False - native Python NoneType
873
874 Args:
875 jsondata: A valid JSON data node.
876 valtype: Type of requested value.
877 parent: Return the parent node of the pointed value.
878
879 Returns:
880 The node reference.
881
882 Raises:
883 JSONPointerException:
884 forwarded from json
885 """
886 if not self:
887 return jsondata
888 if len(self) == 1 and self[0] == '':
889 return jsondata['']
890
891 if type(jsondata) not in VALID_NODE_TYPE:
892
893 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
894
895 try:
896 if parent:
897 for x in self[:-1]:
898 jsondata=jsondata[x]
899 else:
900 for x in self:
901 jsondata=jsondata[x]
902 except Exception as e:
903 raise JSONPointerException("Node("+str(self.index(x))+"):"+str(x)+" of "+str(self)+":"+str(e))
904 if valtype:
905
906 if valtype in (int,float):
907 if jsondata.isdigit():
908 jsondata = int(jsondata)
909 elif valtype in (int,float):
910
911 if jsondata.isdigit():
912 jsondata = float(jsondata)
913
914 if not type(jsondata) is valtype:
915 raise JSONPointerException("Invalid path value type:"+str(type(valtype))+" != "+str(type(jsondata)))
916 else:
917 if type(jsondata) not in VALID_NODE_TYPE:
918 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
919 self.node = jsondata
920 return jsondata
921
923 """Returns the node for valid part of the pointer, and the remaining part.
924
925 This method works similar to the 'get_node' method, whereas it
926 handles partial valid path pointers, which may also include
927 a '-' in accordance to RFC6902.
928
929 Therefore the non-ambiguous part of the pointer is resolved,
930 and returned with the remaining part for a newly create.
931 Thus this method is in particular foreseen to support the
932 creation of new sub data structures.
933
934 The 'get_node' method therefore returns a list of two elements,
935 the first is the node reference, the second the list of the
936 remaining path pointer components. The latter may be empty in
937 case of a fully valid pointer.
938
939
940 Args:
941 jsondata: A valid JSON data node.
942 parent: Return the parent node of the pointed value.
943
944 Returns:
945 The node reference, and the remaining part.
946 ret:=[ node, [<remaining-path-components-list>] ]
947
948 Raises:
949 JSONPointerException:
950 forwarded from json
951 """
952 if self == []:
953 return jsondata
954 if self == ['']:
955 return jsondata['']
956
957 if type(jsondata) not in (dict, list):
958
959 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
960 remaining = None
961 try:
962 if parent:
963 for x in self[:-1]:
964 remaining = x
965 jsondata=jsondata[x]
966 else:
967 for x in self:
968 remaining = x
969 jsondata=jsondata[x]
970 except Exception:
971 if parent:
972 remaining = self[self.index(remaining):-1]
973 else:
974 remaining = self[self.index(remaining):]
975 if type(jsondata) not in (dict, list):
976
977 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
978 self.node = jsondata
979 return [jsondata, remaining]
980
982 """Gets for the corresponding path list of the object pointer for in-memory access on the data of the 'json' package.
983
984 Args:
985 none
986
987 Returns:
988 The path list.
989
990 Raises:
991 none
992 """
993 if __debug__:
994 if self.debug:
995 print repr(self)
996 return list(self)
997
999 """Gets for the corresponding path list of the object pointer for in-memory access on the data of the 'json' package.
1000
1001 Args:
1002 none
1003
1004 Returns:
1005 The path list.
1006
1007 Raises:
1008 none
1009 """
1010 if len(self)>2:
1011 return self[:-1],self[-1]
1012 elif len(self)==1:
1013 return [],self[-1]
1014 elif len(self)==0:
1015 return [],None
1016
1017 - def get_pointer(self,forcenotation=None,parent=False):
1018 """Gets the objects pointer in compliance to RFC6901.
1019
1020 Args:
1021 forcenotation: Force the output notation to:
1022 None := NOTATION_JSON,
1023 NOTATION_JSON = 0,
1024 NOTATION_HTTP_FRAGMENT = 1
1025
1026 parent: Get parent of selected node.
1027
1028 Returns:
1029 The pointer in accordance to RFC6901.
1030
1031 Raises:
1032 none
1033 """
1034 if not self:
1035 return ''
1036 if len(self) == 1 and self[0] == '':
1037 return '/'
1038
1039 if parent:
1040 return unicode('/'+'/'.join(map(unicode,self[:-1])))
1041 else:
1042 return unicode('/'+'/'.join(map(unicode,self)))
1043
1045 """Gets the objects raw 6901-pointer.
1046
1047 Args:
1048 none
1049
1050 Returns:
1051 The raw path.
1052
1053 Raises:
1054 none
1055 """
1056 return self.raw
1057
1058 - def iter_path(self,jsondata=None,parent=False,rev=False):
1059 """Iterator for the elements of the path pointer itself.
1060
1061 Args:
1062 jsondata: If provided a valid JSON data node, the
1063 path components are successively verified on
1064 the provided document. If None the path pointer
1065 components are just iterated.
1066 parent: Uses the path pointer to parent node.
1067 rev: Reverse the order, start with last.
1068
1069 Returns:
1070 Yields the iterator for the current path pointer
1071 component.
1072
1073 Raises:
1074 JSONPointerException:
1075 forwarded from json
1076 """
1077 if self.ptr == []:
1078 yield ''
1079 elif self.ptr == ['']:
1080 yield '/'
1081 else:
1082 if jsondata and type(jsondata) not in (dict, list):
1083
1084 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
1085
1086 if rev:
1087 if parent:
1088 ptrpath = self.ptr[:-1:-1]
1089 else:
1090 ptrpath = self.ptr[::-1]
1091 else:
1092 if parent:
1093 ptrpath = self.ptr[:-1]
1094 else:
1095 ptrpath = self.ptr
1096
1097 try:
1098 x = ptrpath[0]
1099 for x in ptrpath:
1100 if jsondata:
1101 jsondata=jsondata[x]
1102 if type(jsondata) not in (dict, list):
1103
1104 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
1105 yield x
1106 except Exception as e:
1107 raise JSONPointerException("Node("+str(ptrpath.index(x))+"):"+str(x)+" of "+str(self.ptr)+":"+str(e))
1108 self.node = jsondata
1109
1111 """Iterator for the elements the path pointer points to.
1112
1113 Args:
1114 jsondata: A valid JSON data node.
1115 parent: Uses the path pointer to parent node.
1116 rev: Reverse the order, start with last.
1117
1118 Returns:
1119 Yields the iterator of the current node reference.
1120
1121 Raises:
1122 JSONPointerException:
1123 forwarded from json
1124 """
1125 if self.ptr == []:
1126 yield jsondata
1127 elif self.ptr == ['']:
1128 yield jsondata['']
1129 else:
1130 if type(jsondata) not in (dict, list):
1131
1132 raise JSONPointerException("Invalid nodetype parameter:"+str(type(jsondata)))
1133
1134 if rev:
1135 if parent:
1136 ptrpath = self.ptr[:-1:-1]
1137 else:
1138 ptrpath = self.ptr[::-1]
1139 else:
1140 if parent:
1141 ptrpath = self.ptr[:-1]
1142 else:
1143 ptrpath = self.ptr
1144
1145 try:
1146 x = ptrpath[0]
1147 for x in ptrpath:
1148 jsondata=jsondata[x]
1149 if type(jsondata) not in (dict, list):
1150
1151 raise JSONPointerException("Invalid path nodetype:"+str(type(jsondata)))
1152 yield jsondata
1153 except Exception as e:
1154 raise JSONPointerException("Node("+str(ptrpath.index(x))+"):"+str(x)+" of "+str(self.ptr)+":"+str(e))
1155 self.node = jsondata
1156