JSON pointer: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(5 intermediate revisions by 2 users not shown)
Line 562:
checkError("/no/such/thing"),
checkError("bad/pointer")
</syntaxhighlight">
{{output}}
Nothing, by design.
Line 817:
 
"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>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">use serde_json::{ json, Value };
 
type JSONPointer = Vec<String>;
 
fn new_json_pointer(pstring: &str) -> Result<JSONPointer, String> {
return jp_parse(pstring);
}
 
fn resolve(p: JSONPointer, data: Value) -> Result<Value, String> {
return p.iter().fold(Ok(data), |accum, val| get_item(accum, val));
}
 
fn jp_parse(pst: &str) -> Result<Vec<String>, String> {
if pst == "" {
return Ok([].to_vec());
}
if pst.chars().nth(0).unwrap() != '/' {
return Err(String::from("Non-empty JSON pointers must begin with /"));
}
return Ok(
pst
.split("/")
.map(|s| String::from(s.replace("~1", "/").replace("~0", "~")))
.collect::<Vec<String>>()[1..]
.to_vec()
);
}
 
fn get_item<'a>(obj: Result<Value, String>, token: &str) -> Result<Value, String> {
match obj {
Err(_) => {
return obj; // propagate along
}
Ok(ob) => {
match ob {
Value::Array(arr) => {
let idx = usize::from_str_radix(token, 10);
match idx {
Err(..) => {
return Err(String::from("ParseIntErr"));
}
Ok(i) => {
if i < arr.len() {
return Ok(Value::String(arr[i].to_string()));
}
return Err(String::from(format!("Index {:?} out of range", token)));
}
}
}
Value::Object(dic) => {
if dic.contains_key(token) {
return Ok(dic[token].clone());
}
return Err(String::from(format!("Key error with {:?}", token)));
}
_ => {
return Err(String::from("Unknown object"));
}
}
}
}
}
 
fn main() {
let doc =
json!({
"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"},
});
let examples = [
"",
"/",
"/ ",
"/abc",
"/def/",
"/g~1h",
"/i~0j",
"/wiki/links/0",
"/wiki/links/1",
"/wiki/links/2",
"/wiki/name",
"/no/such/thing",
"bad/pointer",
];
for p in examples {
let jspointer = new_json_pointer(p);
match jspointer {
Err(error) => println!("JSON pointer creation error: {error}"),
Ok(pointer) => {
let result = resolve(pointer, doc.clone());
match result {
Ok(val) => println!("\"{p}\" -> {val}"),
Err(err) => println!("Error: {p} does not exist: {err}"),
}
}
}
}
}
</syntaxhighlight>{{out}}
<pre>
"" -> {"":"Rosetta"," ":"Code","abc":["is","a"],"def":{"":"programming"},"g/h":"chrestomathy","i~j":"site","wiki":{"links":["https://rosettacode.org/wiki/Rosetta_Code","https://discord.com/channels/1011262808001880065"]}}
"/" -> "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: Index "2" out of range
Error: /wiki/name does not exist: Key error with "name"
Error: /no/such/thing does not exist: Key error with "no"
JSON pointer creation error: Non-empty JSON pointers must begin with /
</pre>
 
Line 822 ⟶ 1,057:
{{libheader|Wren-json}}
{{libheader|Wren-iterate}}
<syntaxhighlight lang="pythonwren">import "./json" for JSON
import "./iterate" for Indexed
 
9,476

edits