update jsonpointer to current spec
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-05
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
#
|
||||
|
||||
""" Identify specific nodes in a JSON document according to
|
||||
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-04 """
|
||||
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-05 """
|
||||
|
||||
# Will be parsed by setup.py to determine package metadata
|
||||
__author__ = 'Stefan Kögl <stefan@skoegl.net>'
|
||||
@@ -54,6 +54,18 @@ class JsonPointerException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class EndOfList(object):
|
||||
""" Result of accessing element "-" of a list """
|
||||
|
||||
def __init__(self, list_):
|
||||
self.list_ = list_
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '{cls}({lst})'.format(cls=self.__class__.__name__,
|
||||
lst=repr(self.list_))
|
||||
|
||||
|
||||
_nothing = object()
|
||||
|
||||
|
||||
@@ -198,25 +210,32 @@ class JsonPointer(object):
|
||||
def walk(self, doc, part):
|
||||
""" Walks one step in doc and returns the referenced part """
|
||||
|
||||
# Its not clear if a location "1" should be considered as 1 or "1"
|
||||
# We prefer the integer-variant if possible
|
||||
part_variants = self._try_parse(part) + [part]
|
||||
|
||||
for variant in part_variants:
|
||||
if isinstance(doc, dict):
|
||||
try:
|
||||
return doc[variant]
|
||||
except:
|
||||
continue
|
||||
return doc[part]
|
||||
|
||||
raise JsonPointerException("'%s' not found in %s" % (part, doc))
|
||||
except KeyError:
|
||||
raise JsonPointerException("member '%s' not found in %s" % (part, doc))
|
||||
|
||||
elif isinstance(doc, list):
|
||||
|
||||
if part == '-':
|
||||
return EndOfList(doc)
|
||||
|
||||
try:
|
||||
part = int(part)
|
||||
except ValueError:
|
||||
raise JsonPointerException("'%s' is not a valid list index" % (part, ))
|
||||
|
||||
try:
|
||||
return doc[part]
|
||||
|
||||
except IndexError:
|
||||
raise JsonPointerException("index '%s' is out of bounds" % (part, ))
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _try_parse(val, cls=int):
|
||||
try:
|
||||
return [cls(val)]
|
||||
except:
|
||||
return []
|
||||
else:
|
||||
raise JsonPointerException("can not go beyond '%s' (type '%s')" % (part, doc.__class__))
|
||||
|
||||
|
||||
|
||||
|
||||
10
tests.py
10
tests.py
@@ -4,7 +4,7 @@
|
||||
import doctest
|
||||
import unittest
|
||||
import sys
|
||||
from jsonpointer import resolve_pointer
|
||||
from jsonpointer import resolve_pointer, EndOfList, JsonPointerException
|
||||
|
||||
class SpecificationTests(unittest.TestCase):
|
||||
""" Tests all examples from the JSON Pointer specification """
|
||||
@@ -37,6 +37,14 @@ class SpecificationTests(unittest.TestCase):
|
||||
self.assertEqual(resolve_pointer(doc, "/m~0n"), 8)
|
||||
|
||||
|
||||
def test_eol(self):
|
||||
doc = {
|
||||
"foo": ["bar", "baz"]
|
||||
}
|
||||
|
||||
self.assertTrue(isinstance(resolve_pointer(doc, "/foo/-"), EndOfList))
|
||||
self.assertRaises(JsonPointerException, resolve_pointer, doc, "/foo/-/1")
|
||||
|
||||
|
||||
|
||||
modules = ['jsonpointer']
|
||||
|
||||
Reference in New Issue
Block a user