JSON pointer: Difference between revisions
Content added Content deleted
Line 926: | Line 926: | ||
Error: /no/such/thing does not exist: 'no' |
Error: /no/such/thing does not exist: 'no' |
||
Error: bad/pointer does not exist: Non-empty JSON pointers must begin with / |
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) -> Vec<String> { |
|||
return jp_parse(pstring).unwrap(); |
|||
} |
|||
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("Index {token} out of range")); |
|||
} |
|||
} |
|||
} |
|||
Value::Object(dic) => { |
|||
if dic.contains_key(token) { |
|||
return Ok(dic[token].clone()); |
|||
} |
|||
return Err(String::from("Key error with {token}")); |
|||
} |
|||
_ => { |
|||
return Err(String::from("Unknown object {obj}")); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
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 pointer = new_json_pointer(p); |
|||
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 {token} out of range |
|||
Error: /wiki/name does not exist: Key error with {token} |
|||
Error: /no/such/thing does not exist: Key error with {token} |
|||
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "Non-empty JSON pointers must begin with /"', src\main.rs:6:30 |
|||
</pre> |
</pre> |
||