1pub use schemars;
20
21use schemars::schema_for;
22
23pub struct Schema {
25 pub value: serde_json::Value,
26}
27
28impl Schema {
29 pub fn new<T: schemars::JsonSchema>() -> Result<Self, serde_json::Error> {
30 let schema = serde_json::to_value(schema_for!(T))?;
31 let mut json_schema = Self { value: schema };
32 json_schema.enforce_openai_subset();
33 Ok(json_schema)
34 }
35
36 fn enforce_openai_subset(&mut self) {
37 Self::remove_property_format_value_from_json(&mut self.value);
38 Self::replace_one_of_by_any_of(&mut self.value);
39 Self::set_additional_properties_to_false(&mut self.value);
40 Self::enforce_all_required_properties(&mut self.value);
41 }
42
43 fn set_additional_properties_to_false(object: &mut serde_json::Value) {
44 match object {
45 serde_json::Value::Object(object) => {
46 if object.get("type") == Some(&serde_json::Value::String("object".into())) {
47 object.insert("additionalProperties".into(), serde_json::Value::Bool(false));
48 }
49 for value in object.values_mut() {
50 Self::set_additional_properties_to_false(value);
51 }
52 }
53 serde_json::Value::Array(array) => {
54 for value in array.iter_mut() {
55 Self::set_additional_properties_to_false(value);
56 }
57 }
58 _ => {}
59 }
60 }
61
62 fn enforce_all_required_properties(object: &mut serde_json::Value) {
63 match object {
64 serde_json::Value::Object(object) => {
65 let properties = object
66 .get_mut("properties")
67 .and_then(|properties| properties.as_object())
68 .map(|properties|
69 properties
70 .keys()
71 .map(|key| serde_json::Value::String(key.to_string()))
72 .collect::<Vec<_>>()
73 );
74 if let (Some(required), Some(properties)) = (object.get_mut("required"), properties) {
75 if let Some(required) = required.as_array_mut() {
76 for property in properties {
77 if !required.contains(&property) {
78 required.push(property);
79 }
80 }
81 }
82 }
83 for value in object.values_mut() {
84 Self::enforce_all_required_properties(value);
85 }
86 },
87 serde_json::Value::Array(array) => {
88 for value in array.iter_mut() {
89 Self::enforce_all_required_properties(value);
90 }
91 }
92 _ => {}
93 }
94 }
95
96 fn replace_one_of_by_any_of(object: &mut serde_json::Value) {
97 match object {
98 serde_json::Value::Object(object) => {
99 for key in ["oneOf", "allOf"] {
100 if object.contains_key(key) {
101 if let Some(value) = object.remove(key) {
102 object.insert("anyOf".into(), value);
103 }
104 }
105 }
106 for value in object.values_mut() {
107 Self::replace_one_of_by_any_of(value);
108 }
109 }
110 serde_json::Value::Array(array) => {
111 for value in array.iter_mut() {
112 Self::replace_one_of_by_any_of(value);
113 }
114 }
115 _ => {}
116 }
117 }
118
119 fn remove_property_format_value_from_json(object: &mut serde_json::Value) {
120 match object {
121 serde_json::Value::Object(object) => {
122 for key in ["minLength", "maxLength", "pattern", "format", "minimum", "maximum", "multipleOf", "patternProperties", "unevaluatedProperties", "propertyNames", "minProperties", "maxProperties", "unevaluatedItems", "contains", "minContains", "maxContains", "minItems", "maxItems", "uniqueItems"] {
123 object.remove(key);
124 }
125 for value in object.values_mut() {
126 Self::remove_property_format_value_from_json(value);
127 }
128 },
129 serde_json::Value::Array(array) => {
130 for value in array.iter_mut() {
131 Self::remove_property_format_value_from_json(value);
132 }
133 },
134 _ => {}
135 }
136 }
137}