JSON pointer: Difference between revisions

Content added Content deleted
Line 817: Line 817:


"bad/pointer" => Error pointers must start with a slash or be the empty string
"bad/pointer" => Error pointers must start with a slash or be the empty string
</pre>

=={{header|Python}}==
{{trans|JavaScript}}
<syntaxhighlight lang="python">""" rosettacode.org/wiki/JSON_pointer """

from functools import reduce


class JSONPointer:
""" datatracker.ietf.org/doc/html/rfc6901 """

def __init__(self, pstring):
""" create a JSON ponter from a string """
self.tokens = parse(pstring)

def resolve(self, data):
""" use the pointer on an object """
return reduce(get_item, self.tokens, data)

def encode(self):
""" output pointer in string form """
ret = ''
for tok in self.tokens:
ret = ret + '/' + tok.replace('~', '~0').replace('/', '~1')
return ret

def to_string(self):
""" output pointer in string form """
return self.encode()


def parse(pst):
""" tokenize a string for use as JSON pointer """
if pst == '':
return []
if pst[0] != '/':
raise SyntaxError('Non-empty JSON pointers must begin with /')
return [a.replace('~1', '/').replace('~0', '~') for a in pst.split('/')][1:]


def get_item(obj, token):
"""
NOTE:
- string primitives 'have own' indices and `length`.
- Arrays have a `length` property.
- A property might exist with the value `undefined`.
- obj[1] is equivalent to obj['1'].
"""
if isinstance(obj, list) and isinstance(token, str):
return obj[int(token)]
return obj[token]


if __name__ == '__main__':

DOC = {
'wiki': {
'links': [
'https://rosettacode.org/wiki/Rosetta_Code',
'https://discord.com/channels/1011262808001880065',
],
},
'': 'Rosetta',
' ': 'Code',
'g/h': 'chrestomathy',
'i~j': 'site',
'abc': ['is', 'a'],
'def': {'': 'programming'},
}

EXAMPLES = [
'',
'/',
'/ ',
'/abc',
'/def/',
'/g~1h',
'/i~0j',
'/wiki/links/0',
'/wiki/links/1',
'/wiki/links/2',
'/wiki/name',
'/no/such/thing',
'bad/pointer',
]

for exa in EXAMPLES:
try:
pointer = JSONPointer(exa)
result = pointer.resolve(DOC)
print(f'"{exa}" -> "{result}"')
except (SyntaxError, IndexError, KeyError) as error:
print(f'Error: {exa} does not exist: {error}')
</syntaxhighlight>{{out}}
<pre>
"" -> "{'wiki': {'links': ['https://rosettacode.org/wiki/Rosetta_Code', 'https://discord.com/channels/1011262808001880065']}, '': 'Rosetta', ' ': 'Code', 'g/h': 'chrestomathy', 'i~j': 'site', 'abc': ['is', 'a'], 'def': {'': 'programming'}}"
"/" -> "Rosetta"
"/ " -> "Code"
"/abc" -> "['is', 'a']"
"/def/" -> "programming"
"/g~1h" -> "chrestomathy"
"/i~0j" -> "site"
"/wiki/links/0" -> "https://rosettacode.org/wiki/Rosetta_Code"
"/wiki/links/1" -> "https://discord.com/channels/1011262808001880065"
Error: /wiki/links/2 does not exist: list index out of range
Error: /wiki/name does not exist: 'name'
Error: /no/such/thing does not exist: 'no'
Error: bad/pointer does not exist: Non-empty JSON pointers must begin with /
</pre>
</pre>