spreadsheet_mcp/
response_prune.rs1use 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}