@@ -3,12 +3,19 @@ use schemars::schema::{
33 ArrayValidation , InstanceType , Metadata , ObjectValidation , Schema , SchemaObject , SingleOrVec ,
44} ;
55
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+
613pub trait ToJsonSchema {
7- fn to_json_schema ( & self ) -> SchemaObject ;
14+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject ;
815}
916
1017impl ToJsonSchema for schema:: BasicValueType {
11- fn to_json_schema ( & self ) -> SchemaObject {
18+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
1219 let mut schema = SchemaObject :: default ( ) ;
1320 match self {
1421 schema:: BasicValueType :: Str => {
@@ -26,9 +33,6 @@ impl ToJsonSchema for schema::BasicValueType {
2633 schema:: BasicValueType :: Float32 | schema:: BasicValueType :: Float64 => {
2734 schema. instance_type = Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Number ) ) ) ;
2835 }
29- schema:: BasicValueType :: Json => {
30- // Can be any value. No type constraint.
31- }
3236 schema:: BasicValueType :: Range => {
3337 schema. instance_type = Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Array ) ) ) ;
3438 schema. array = Some ( Box :: new ( ArrayValidation {
@@ -51,11 +55,18 @@ impl ToJsonSchema for schema::BasicValueType {
5155 . description =
5256 Some ( "A range, start pos (inclusive), end pos (exclusive)." . to_string ( ) ) ;
5357 }
58+ schema:: BasicValueType :: Uuid => {
59+ schema. instance_type = Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: String ) ) ) ;
60+ schema. format = Some ( "uuid" . to_string ( ) ) ;
61+ }
62+ schema:: BasicValueType :: Json => {
63+ // Can be any value. No type constraint.
64+ }
5465 schema:: BasicValueType :: Vector ( s) => {
5566 schema. instance_type = Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Array ) ) ) ;
5667 schema. array = Some ( Box :: new ( ArrayValidation {
5768 items : Some ( SingleOrVec :: Single ( Box :: new (
58- s. element_type . to_json_schema ( ) . into ( ) ,
69+ s. element_type . to_json_schema ( options ) . into ( ) ,
5970 ) ) ) ,
6071 min_items : s. dimension . and_then ( |d| u32:: try_from ( d) . ok ( ) ) ,
6172 max_items : s. dimension . and_then ( |d| u32:: try_from ( d) . ok ( ) ) ,
@@ -68,7 +79,7 @@ impl ToJsonSchema for schema::BasicValueType {
6879}
6980
7081impl ToJsonSchema for schema:: StructSchema {
71- fn to_json_schema ( & self ) -> SchemaObject {
82+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
7283 SchemaObject {
7384 metadata : Some ( Box :: new ( Metadata {
7485 description : self . description . as_ref ( ) . map ( |s| s. to_string ( ) ) ,
@@ -79,12 +90,25 @@ impl ToJsonSchema for schema::StructSchema {
7990 properties : self
8091 . fields
8192 . iter ( )
82- . 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+ } )
83107 . collect ( ) ,
84108 required : self
85109 . fields
86110 . iter ( )
87- . filter ( |& f| ( !f. value_type . nullable ) )
111+ . filter ( |& f| ( options . fields_always_required || !f. value_type . nullable ) )
88112 . map ( |f| f. name . to_string ( ) )
89113 . collect ( ) ,
90114 additional_properties : Some ( Schema :: Bool ( false ) . into ( ) ) ,
@@ -96,14 +120,16 @@ impl ToJsonSchema for schema::StructSchema {
96120}
97121
98122impl ToJsonSchema for schema:: ValueType {
99- fn to_json_schema ( & self ) -> SchemaObject {
123+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
100124 match self {
101- schema:: ValueType :: Basic ( b) => b. to_json_schema ( ) ,
102- 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 ) ,
103127 schema:: ValueType :: Collection ( c) => SchemaObject {
104128 instance_type : Some ( SingleOrVec :: Single ( Box :: new ( InstanceType :: Array ) ) ) ,
105129 array : Some ( Box :: new ( ArrayValidation {
106- 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+ ) ) ) ,
107133 ..Default :: default ( )
108134 } ) ) ,
109135 ..Default :: default ( )
@@ -113,7 +139,7 @@ impl ToJsonSchema for schema::ValueType {
113139}
114140
115141impl ToJsonSchema for schema:: EnrichedValueType {
116- fn to_json_schema ( & self ) -> SchemaObject {
117- self . typ . to_json_schema ( )
142+ fn to_json_schema ( & self , options : & ToJsonSchemaOptions ) -> SchemaObject {
143+ self . typ . to_json_schema ( options )
118144 }
119145}
0 commit comments