Macro dyn_access

Source
macro_rules! dyn_access {
    ($head:ident $($rest:tt)*) => { ... };
    (($head:expr) $($rest:tt)*) => { ... };
    (@recurse $acc:expr, . $field:ident $($rest:tt)*) => { ... };
    (@recurse $acc:expr, [$idx:expr] $($rest:tt)*) => { ... };
    (@recurse $acc:expr,) => { ... };
}
Expand description

§dyn_access

The dyn_access has a specific use-case, which is accessing very deeply nested values in parsed structures.

For example, imagine you have an API, which you only need some data for. Usually in JavaScript you simply fetch a value and access it dinamically with a path like value?.nested?.nested[0] then simply check for undefined.

This macro permits you access to very nested objects with javascript like indexers, with the exception you don’t need to use ?, as you get an Option<T> instead.

This macro is recursive and will stop working when the value doesn’t have a .get method that returns an Option.

To invoke this macro you just use a path like

use serde_json::json;
use dyn_path::dyn_access;

let object = json!({
    "very": {
        "nested": {
            "value": [
                "hello",
                "world"
            ]
        }
    }
});

let hello = dyn_access!(object.very.nested.value[0]).unwrap();
let world = dyn_access!(object.very.nested.value[1]).unwrap();

assert_eq!(hello, "hello");
assert_eq!(world, "world");

You also have indices available to you, whether it is for an array or an object.

Notice how the first element is the name of the variable, you can have an expression in there with parenthesis like (value.parse::<serde_json::Value>()?).very.nested.value, the parenthesis are due to parsing system limitation since this is a macro_rules and not a proc_macro.