Skip to main content

spreadsheet_mcp/
response_prune.rs

1use anyhow::Result;
2use schemars::{JsonSchema, Schema, SchemaGenerator};
3use serde::Serialize;
4use serde::ser::Error as _;
5use serde_json::Value;
6use std::borrow::Cow;
7
8pub fn to_pruned_value<T: Serialize>(value: &T) -> Result<Value> {
9    let mut json = serde_json::to_value(value)?;
10    prune_non_structural_empties(&mut json);
11    Ok(json)
12}
13
14#[derive(Debug, Clone)]
15pub struct Pruned<T>(pub T);
16
17impl<T: Serialize> Serialize for Pruned<T> {
18    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19    where
20        S: serde::Serializer,
21    {
22        let mut value = serde_json::to_value(&self.0).map_err(S::Error::custom)?;
23        prune_non_structural_empties(&mut value);
24        value.serialize(serializer)
25    }
26}
27
28impl<T: JsonSchema> JsonSchema for Pruned<T> {
29    fn schema_name() -> Cow<'static, str> {
30        T::schema_name()
31    }
32
33    fn json_schema(generator: &mut SchemaGenerator) -> Schema {
34        T::json_schema(generator)
35    }
36}
37
38pub fn prune_non_structural_empties(value: &mut Value) {
39    match value {
40        Value::Object(map) => {
41            let mut remove_keys = Vec::new();
42            for (key, child) in map.iter_mut() {
43                prune_non_structural_empties(child);
44                if child.is_null() {
45                    remove_keys.push(key.clone());
46                    continue;
47                }
48                if let Value::Object(obj) = child
49                    && obj.is_empty()
50                {
51                    remove_keys.push(key.clone());
52                    continue;
53                }
54                if let Value::Array(arr) = child
55                    && arr.is_empty()
56                {
57                    remove_keys.push(key.clone());
58                }
59            }
60            for key in remove_keys {
61                map.remove(&key);
62            }
63        }
64        Value::Array(items) => {
65            for child in items.iter_mut() {
66                prune_non_structural_empties(child);
67            }
68        }
69        _ => {}
70    }
71}