@@ -3,12 +3,19 @@ use schemars::schema::{
3
3
ArrayValidation , InstanceType , Metadata , ObjectValidation , Schema , SchemaObject , SingleOrVec ,
4
4
} ;
5
5
6
+ pub struct ToJsonSchemaOptions {
7
+ /// If true, mark all fields as required.
8
+ /// Use union type (with `null`) for optional fields instead.
9
+ /// Models like OpenAI will reject the schema if a field is not required.
10
+ pub fields_always_required : bool ,
11
+ }
12
+
6
13
pub trait ToJsonSchema {
7
- fn to_json_schema ( & self ) -> SchemaObject ;
14
+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject ;
8
15
}
9
16
10
17
impl ToJsonSchema for schema:: BasicValueType {
11
- fn to_json_schema ( & self ) -> SchemaObject {
18
+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
12
19
let mut schema = SchemaObject :: default ( ) ;
13
20
match self {
14
21
schema:: BasicValueType :: Str => {
@@ -59,7 +66,7 @@ impl ToJsonSchema for schema::BasicValueType {
59
66
schema. instance_type = Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Array ) ) ) ;
60
67
schema. array = Some ( Box :: new ( ArrayValidation {
61
68
items : Some ( SingleOrVec :: Single ( Box :: new (
62
- s. element_type . to_json_schema ( ) . into ( ) ,
69
+ s. element_type . to_json_schema ( options ) . into ( ) ,
63
70
) ) ) ,
64
71
min_items : s. dimension . and_then ( |d| u32:: try_from ( d) . ok ( ) ) ,
65
72
max_items : s. dimension . and_then ( |d| u32:: try_from ( d) . ok ( ) ) ,
@@ -72,7 +79,7 @@ impl ToJsonSchema for schema::BasicValueType {
72
79
}
73
80
74
81
impl ToJsonSchema for schema:: StructSchema {
75
- fn to_json_schema ( & self ) -> SchemaObject {
82
+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
76
83
SchemaObject {
77
84
metadata : Some ( Box :: new ( Metadata {
78
85
description : self . description . as_ref ( ) . map ( |s| s. to_string ( ) ) ,
@@ -83,12 +90,25 @@ impl ToJsonSchema for schema::StructSchema {
83
90
properties : self
84
91
. fields
85
92
. iter ( )
86
- . map ( |f| ( f. name . to_string ( ) , f. value_type . to_json_schema ( ) . into ( ) ) )
93
+ . map ( |f| {
94
+ let mut schema = f. value_type . to_json_schema ( options) ;
95
+ if options. fields_always_required && f. value_type . nullable {
96
+ if let Some ( instance_type) = & mut schema. instance_type {
97
+ let mut types = match instance_type {
98
+ SingleOrVec :: Single ( t) => vec ! [ * * t] ,
99
+ SingleOrVec :: Vec ( t) => std:: mem:: take ( t) ,
100
+ } ;
101
+ types. push ( InstanceType :: Null ) ;
102
+ * instance_type = SingleOrVec :: Vec ( types) ;
103
+ }
104
+ }
105
+ ( f. name . to_string ( ) , schema. into ( ) )
106
+ } )
87
107
. collect ( ) ,
88
108
required : self
89
109
. fields
90
110
. iter ( )
91
- . filter ( |& f| ( !f. value_type . nullable ) )
111
+ . filter ( |& f| ( options . fields_always_required || !f. value_type . nullable ) )
92
112
. map ( |f| f. name . to_string ( ) )
93
113
. collect ( ) ,
94
114
additional_properties : Some ( Schema :: Bool ( false ) . into ( ) ) ,
@@ -100,14 +120,16 @@ impl ToJsonSchema for schema::StructSchema {
100
120
}
101
121
102
122
impl ToJsonSchema for schema:: ValueType {
103
- fn to_json_schema ( & self ) -> SchemaObject {
123
+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
104
124
match self {
105
- schema:: ValueType :: Basic ( b) => b. to_json_schema ( ) ,
106
- schema:: ValueType :: Struct ( s) => s. to_json_schema ( ) ,
125
+ schema:: ValueType :: Basic ( b) => b. to_json_schema ( options ) ,
126
+ schema:: ValueType :: Struct ( s) => s. to_json_schema ( options ) ,
107
127
schema:: ValueType :: Collection ( c) => SchemaObject {
108
128
instance_type : Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Array ) ) ) ,
109
129
array : Some ( Box :: new ( ArrayValidation {
110
- items : Some ( SingleOrVec :: Single ( Box :: new ( c. row . to_json_schema ( ) . into ( ) ) ) ) ,
130
+ items : Some ( SingleOrVec :: Single ( Box :: new (
131
+ c. row . to_json_schema ( options) . into ( ) ,
132
+ ) ) ) ,
111
133
..Default :: default ( )
112
134
} ) ) ,
113
135
..Default :: default ( )
@@ -117,7 +139,7 @@ impl ToJsonSchema for schema::ValueType {
117
139
}
118
140
119
141
impl ToJsonSchema for schema:: EnrichedValueType {
120
- fn to_json_schema ( & self ) -> SchemaObject {
121
- self . typ . to_json_schema ( )
142
+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
143
+ self . typ . to_json_schema ( options )
122
144
}
123
145
}
0 commit comments