hiltontj / serde_json_path

Query serde_json Values with JSONPath
https://serdejsonpath.live/
MIT License
50 stars 3 forks source link

[11] `NodeList` API Improvements #13

Closed hiltontj closed 1 year ago

hiltontj commented 1 year ago

This PR extends the NodeList type's API to include two new methods: NodeList::exactly_one and NodeList::at_most_one.

Consider the following Value:

let value = json!({"foo": ["bar", "baz"]});

The at_most_one method is meant to replace the original one method. It works similarly, however, is fallible in the case where more than one node is produced by the query:

let path = JsonPath::parse("$.foo[10]")?;
let node = path.query(&value).at_most_one().unwrap();
assert_eq!(node, None);
let path = JsonPath::parse("$.foo[0]")?;
let node = path.query(&value).at_most_one().unwrap();
assert_eq!(node, Some(&json!("bar")));
let path = JsonPath::parse("$.foo.*")?;
let error = path.query(&value).at_most_one().unwrap_err();
assert!(matches!(error, AtMostOneError(2)));

The exactly_one method is similar, but for cases where a JSON Path is expected to return exactly a single node, and you want to raise an error when it does not.

let value = json!({"foo": ["bar", "baz"]});
let path = JsonPath::parse("$.foo[0]")?;
let node = path.query(&value).exactly_one().unwrap();
assert_eq!(node, "bar");
let path = JsonPath::parse("$.foo[-10]")?;
let error = path.query(&value).exactly_one().unwrap_err();
assert!(matches!(error, ExactlyOneError::Empty));
let path = JsonPath::parse("$.foo.*")?;
let error = path.query(&value).exactly_one().unwrap_err();
assert!(matches!(error, ExactlyOneError::MoreThanOne(2)));

The one method was left in the API, with a deprecation notice, so that this would not be a breaking change.