Created
November 30, 2019 17:52
-
-
Save opethe1st/e425e659ee60401be86da3b8cfc70f10 to your computer and use it in GitHub Desktop.
Implementation of JsonPointer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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