use super::error::*;
use json::JsonValue;
use std::collections::{HashMap, HashSet};
pub fn open_json_from_path(path: &str) -> Result<JsonValue, Error> {
map_err(
json::parse(&map_err(
std::fs::read_to_string(path),
&format!("Could not read {}", path),
)?),
&format!("Could not parse {}", path),
)
}
pub fn json_to_set(json: &JsonValue) -> HashSet<String> {
let mut set = HashSet::<String>::new();
json.members().for_each(|x| {
set.insert(x.as_str().unwrap().to_owned());
});
set
}
pub fn json_to_map<'a>(json: &'a JsonValue) -> HashMap<String, &'a JsonValue> {
let mut map = HashMap::<String, &'a JsonValue>::new();
for (k, v) in json.entries() {
map.insert(k.to_owned(), v);
}
map
}
pub trait FromJson {
type Output;
fn parse(json: JsonValue) -> Result<Self::Output, Error>;
}
impl FromJson for i32 {
type Output = i32;
fn parse(json: JsonValue) -> Result<i32, Error> {
ok_or_else(json.as_i32(), &format!("Could not parse {} as i32", json))
}
}
impl FromJson for i64 {
type Output = i64;
fn parse(json: JsonValue) -> Result<i64, Error> {
ok_or_else(json.as_i64(), &format!("Could not parse {} as i64", json))
}
}
impl FromJson for u32 {
type Output = u32;
fn parse(json: JsonValue) -> Result<u32, Error> {
ok_or_else(json.as_u32(), &format!("Could not parse {} as u32", json))
}
}
impl FromJson for u64 {
type Output = u64;
fn parse(json: JsonValue) -> Result<u64, Error> {
ok_or_else(json.as_u64(), &format!("Could not parse {} as u64", json))
}
}
impl FromJson for String {
type Output = String;
fn parse(json: JsonValue) -> Result<String, Error> {
ok_or_else(
json.as_str().map(|s| s.to_owned()),
&format!("Could not parse {} as String", json),
)
}
}
impl FromJson for bool {
type Output = bool;
fn parse(json: JsonValue) -> Result<bool, Error> {
ok_or_else(json.as_bool(), &format!("Could not parse {} as bool", json))
}
}
pub fn field_is_null(json: &JsonValue, key: &str) -> Result<bool, Error> {
if json.is_null() {
return Error::new("Cannot get field from null json").to_res();
}
if !json.has_key(key) {
Error::new(&format!("Value {} does not have {} field", json, key)).to_res()
} else {
Ok(json[key].is_null())
}
}
pub fn get_field<T: FromJson>(json: &JsonValue, key: &str) -> Result<T::Output, Error> {
if json.is_null() {
return Error::new("Cannot get field from null json").to_res();
}
if !json.has_key(key) {
Error::new(&format!("Value {} does not have {} field", json, key)).to_res()
} else {
T::parse(json[key].clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_open_json_from_path() {
assert!(open_json_from_path("tests/data/keywords/fp_others.json").is_ok());
assert!(open_json_from_path("tests/data/keywords/nonexistent.json").is_err());
assert!(open_json_from_path("tests/data/small_file.csv").is_err());
}
#[test]
fn test_json_to_set() {
let json = json::parse(r#"["a", "b", "c"]"#).unwrap();
let set = json_to_set(&json);
assert_eq!(set.len(), 3);
assert!(set.contains("a"));
assert!(set.contains("b"));
assert!(set.contains("c"));
}
}