use serde_json::Value;
pub const SMALL_THRESHOLD: usize = 1024 * 1024; pub const MEDIUM_THRESHOLD: usize = 10 * 1024 * 1024; pub const LARGE_THRESHOLD: usize = 100 * 1024 * 1024;
pub const SMALL_DEPTH: usize = 30;
pub const MEDIUM_DEPTH: usize = 20;
pub const LARGE_DEPTH: usize = 10;
pub const VERY_LARGE_DEPTH: usize = 5;
pub fn calculate_schema_depth(json_size: usize) -> usize {
if json_size < SMALL_THRESHOLD {
SMALL_DEPTH
} else if json_size < MEDIUM_THRESHOLD {
MEDIUM_DEPTH
} else if json_size < LARGE_THRESHOLD {
LARGE_DEPTH
} else {
VERY_LARGE_DEPTH
}
}
pub fn extract_json_schema(json: &str, max_depth: usize) -> Option<String> {
let value: Value = serde_json::from_str(json).ok()?;
let schema_value = value_to_schema(&value, 0, max_depth)?;
serde_json::to_string(&schema_value).ok()
}
pub fn extract_json_schema_dynamic(json: &str) -> Option<String> {
let depth = calculate_schema_depth(json.len());
extract_json_schema(json, depth)
}
pub fn extract_first_json_value(input: &str) -> Option<String> {
let mut deserializer =
serde_json::Deserializer::from_str(input).into_iter::<serde_json::Value>();
deserializer.next()?.ok().map(|v| v.to_string())
}
fn value_to_schema(value: &Value, current_depth: usize, max_depth: usize) -> Option<Value> {
if current_depth >= max_depth {
return Some(Value::String("...".to_string()));
}
match value {
Value::Null => Some(Value::String("null".to_string())),
Value::Bool(_) => Some(Value::String("boolean".to_string())),
Value::Number(_) => Some(Value::String("number".to_string())),
Value::String(_) => Some(Value::String("string".to_string())),
Value::Array(arr) => {
if arr.is_empty() {
Some(Value::Array(vec![]))
} else {
let first_schema = value_to_schema(&arr[0], current_depth + 1, max_depth)?;
Some(Value::Array(vec![first_schema]))
}
}
Value::Object(map) => {
let mut schema_map = serde_json::Map::new();
for (key, val) in map {
let val_schema = value_to_schema(val, current_depth + 1, max_depth)?;
schema_map.insert(key.clone(), val_schema);
}
Some(Value::Object(schema_map))
}
}
}
#[cfg(test)]
#[path = "json_tests.rs"]
mod json_tests;