better_config_loader/
json.rs1use better_config_core::{AbstractConfig, Error};
2use std::collections::HashMap;
3use std::fs;
4
5pub trait JsonConfig<T = HashMap<String, String>>: AbstractConfig<T> {
7 fn load(target: Option<String>) -> Result<T, Error>
15 where
16 T: Default,
17 HashMap<String, String>: Into<T>,
18 Self: Sized,
19 {
20 let target = target.or(Some("config.json".to_string()));
21
22 let mut json_map = HashMap::new();
23
24 if let Some(target) = target {
25 let file_paths: Vec<String> = target
26 .split(',')
27 .map(|s| s.trim().to_string())
28 .filter(|s| !s.is_empty())
29 .collect();
30
31 for file_path in file_paths {
32 let content = fs::read_to_string(&file_path).map_err(|e| Error::LoadFileError {
33 name: file_path.clone(),
34 source: Some(Box::new(e)),
35 })?;
36
37 let value: serde_json::Value = serde_json::from_str(&content).map_err(|e| Error::LoadFileError {
38 name: file_path.clone(),
39 source: Some(Box::new(e)),
40 })?;
41
42 flatten_json_value(&value, None, &mut json_map);
43 }
44 }
45
46 Ok(json_map.into())
47 }
48}
49
50fn flatten_json_value(value: &serde_json::Value, parent_key: Option<String>, map: &mut HashMap<String, String>) {
51 match value {
52 serde_json::Value::Object(obj) => {
53 for (key, val) in obj {
54 let new_key = match &parent_key {
55 Some(parent) => format!("{}.{}", parent, key),
56 None => key.to_string(),
57 };
58 flatten_json_value(val, Some(new_key), map);
59 }
60 }
61 serde_json::Value::Array(arr) => {
62 for (i, val) in arr.iter().enumerate() {
63 let new_key = match &parent_key {
64 Some(parent) => format!("{}[{}]", parent, i),
65 None => i.to_string(),
66 };
67 flatten_json_value(val, Some(new_key), map);
68 }
69 }
70 serde_json::Value::String(s) => {
71 if let Some(key) = parent_key {
72 map.insert(key, s.to_string());
73 }
74 }
75 serde_json::Value::Number(n) => {
76 if let Some(key) = parent_key {
77 if n.is_i64() {
78 map.insert(key, n.as_i64().unwrap().to_string());
79 } else if n.is_f64() {
80 map.insert(key, n.as_f64().unwrap().to_string());
81 } else {
82 map.insert(key, n.to_string());
83 }
84 }
85 }
86 serde_json::Value::Bool(b) => {
87 if let Some(key) = parent_key {
88 map.insert(key, b.to_string());
89 }
90 }
91 serde_json::Value::Null => {}
92 }
93}