Skip to content

Instantly share code, notes, and snippets.

@opethe1st
Created November 30, 2019 17:52
Show Gist options
  • Save opethe1st/e425e659ee60401be86da3b8cfc70f10 to your computer and use it in GitHub Desktop.
Save opethe1st/e425e659ee60401be86da3b8cfc70f10 to your computer and use it in GitHub Desktop.
Implementation of JsonPointer
def dereference(value, pointer):
tokens = get_reference_tokens(pointer)
current_value = value
while tokens:
current = tokens.pop(0)
if current == "":
return current_value
elif isinstance(current_value, dict):
if current in current_value:
current_value = current_value[current]
else:
raise Exception('')
elif isinstance(current_value, list):
try:
current_int = int(current)
except Exception:
raise Exception(f'Couldnt convert {current} to int')
if 0 <= current_int < len(current_value):
current_value = current_value[current_int]
else:
raise Exception('')
else:
raise Exception('')
return current_value
def get_reference_tokens(pointer):
tokens = pointer.split('/')
tokens = tokens[1:] if tokens[0] == '' else tokens
tokens = [token.replace('~1', '/') for token in tokens]
return [token.replace('~0', '~') for token in tokens]
# tests
import unittest
from parameterized import parameterized
from jsonpointer import dereference, get_reference_tokens
class TestDereference(unittest.TestCase):
@parameterized.expand([
('name', ('', ''), ''),
('name', ('value', ''), 'value'),
('name', (['value'], '/0'), 'value'),
('name', ({'key': 'value'}, '/key'), 'value'),
('get array from dict', ({'key': ['value']}, '/key'), ['value']),
('dict then array', ({'key': ['value']}, '/key/0'), 'value'),
])
def test(self, name, inp, output):
value, pointer = inp
self.assertEqual(dereference(value, pointer), output)
@parameterized.expand([
('name', (['value'], '/1'), Exception),
('name', ('value', '12'), Exception),
('name', (['value'], 'ab'), Exception),
])
def test_exception(self, name, inp, exception):
value, pointer = inp
with self.assertRaises(exception):
dereference(value, pointer)
class TestGetReferenceTokens(unittest.TestCase):
@parameterized.expand([
('name', '/abc/cde', ['abc', 'cde']),
('name', '/abc/cde', ['abc', 'cde']),
('name', '/ab~1c/cde~0', ['ab/c', 'cde~']),
('name', '/~01', ['~1']),
('name', '/~10', ['/0']),
('name', '/key/value', ['key', 'value']),
])
def test(self, name, inp, output):
self.assertEqual(get_reference_tokens(inp), output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment