use serde_json::Value;
pub trait ValueExt {
fn str_field(&self, keys: &[&str]) -> Option<&str>;
fn f64_field(&self, keys: &[&str]) -> Option<f64>;
fn i64_field(&self, keys: &[&str]) -> Option<i64>;
fn str_or(&self, keys: &[&str], default: &str) -> String;
fn f64_or(&self, keys: &[&str], default: f64) -> f64;
fn i64_or(&self, keys: &[&str], default: i64) -> i64;
fn nested(&self, path: &[&str]) -> Option<&Value>;
}
impl ValueExt for Value {
fn str_field(&self, keys: &[&str]) -> Option<&str> {
for k in keys {
if let Some(s) = self.get(k).and_then(Self::as_str) {
return Some(s);
}
}
None
}
fn f64_field(&self, keys: &[&str]) -> Option<f64> {
for k in keys {
if let Some(v) = self.get(k).and_then(Self::as_f64) {
return Some(v);
}
}
None
}
fn i64_field(&self, keys: &[&str]) -> Option<i64> {
for k in keys {
if let Some(v) = self.get(k).and_then(Self::as_i64) {
return Some(v);
}
}
None
}
fn str_or(&self, keys: &[&str], default: &str) -> String {
self.str_field(keys).unwrap_or(default).to_string()
}
fn f64_or(&self, keys: &[&str], default: f64) -> f64 {
self.f64_field(keys).unwrap_or(default)
}
fn i64_or(&self, keys: &[&str], default: i64) -> i64 {
self.i64_field(keys).unwrap_or(default)
}
fn nested(&self, path: &[&str]) -> Option<&Value> {
let mut current = self;
for k in path {
current = current.get(k)?;
}
Some(current)
}
}