1515using Microsoft . Extensions . AI . JsonSchemaExporter ;
1616using Xunit ;
1717
18+ #pragma warning disable 0618 // Suppress obsolete warnings
19+
1820namespace Microsoft . Extensions . AI ;
1921
2022public static partial class AIJsonUtilitiesTests
@@ -72,10 +74,11 @@ public static void AIJsonSchemaCreateOptions_DefaultInstance_ReturnsExpectedValu
7274 {
7375 AIJsonSchemaCreateOptions options = useSingleton ? AIJsonSchemaCreateOptions. Default : new AIJsonSchemaCreateOptions ( ) ;
7476 Assert . True ( options . IncludeTypeInEnumSchemas ) ;
75- Assert . True ( options . DisallowAdditionalProperties ) ;
77+ Assert . False ( options . DisallowAdditionalProperties ) ;
7678 Assert . False ( options . IncludeSchemaKeyword ) ;
7779 Assert . False ( options . RequireAllProperties ) ;
7880 Assert . Null ( options . TransformSchemaNode ) ;
81+ Assert . Null ( options . TransformOptions ) ;
7982 }
8083
8184 [ Fact ]
@@ -106,6 +109,12 @@ public static void AIJsonSchemaCreateOptions_UsesStructuralEquality()
106109 property.SetValue(options2, includeParameter);
107110 break;
108111
112+ case null when property.PropertyType == typeof(AIJsonSchemaTransformOptions):
113+ AIJsonSchemaTransformOptions transformOptions = new AIJsonSchemaTransformOptions { RequireAllProperties = true } ;
114+ property.SetValue(options1, transformOptions);
115+ property.SetValue(options2, transformOptions);
116+ break;
117+
109118 default:
110119 Assert.Fail($" Unexpected property type: { property. PropertyType } ") ;
111120 break ;
@@ -152,8 +161,7 @@ public static void CreateJsonSchema_DefaultParameters_GeneratesExpectedJsonSchem
152161 "default": "defaultValue"
153162 }
154163 },
155- "required": ["Key", "EnumValue"],
156- "additionalProperties": false
164+ "required": ["Key", "EnumValue"]
157165 }
158166 """ ) . RootElement ;
159167
@@ -176,23 +184,28 @@ public static void CreateJsonSchema_OverriddenParameters_GeneratesExpectedJsonSc
176184 "type": "integer"
177185 },
178186 "EnumValue": {
187+ "type": "string",
179188 "enum": ["A", "B"]
180189 },
181190 "Value": {
182191 "description": "Default value: \"defaultValue\"",
183192 "type": ["string", "null"]
184193 }
185194 },
186- "required": ["Key", "EnumValue", "Value"]
195+ "required": ["Key", "EnumValue", "Value"],
196+ "additionalProperties": false
187197 }
188198 """ ) . RootElement ;
189199
190200 AIJsonSchemaCreateOptions inferenceOptions = new AIJsonSchemaCreateOptions
191201 {
192- IncludeTypeInEnumSchemas = false ,
193- DisallowAdditionalProperties = false ,
194202 IncludeSchemaKeyword = true ,
195- RequireAllProperties = true ,
203+ TransformOptions = new ( )
204+ {
205+ DisallowAdditionalProperties = true ,
206+ RequireAllProperties = true ,
207+ MoveDefaultKeywordToDescription = true ,
208+ }
196209 } ;
197210
198211 JsonElement actual = AIJsonUtilities . CreateJsonSchema (
@@ -227,8 +240,7 @@ public static void CreateJsonSchema_UserDefinedTransformer()
227240 "default": "defaultValue"
228241 }
229242 },
230- "required": ["Key", "EnumValue"],
231- "additionalProperties": false
243+ "required": ["Key", "EnumValue"]
232244 }
233245 """ ) . RootElement ;
234246
@@ -268,8 +280,7 @@ public static void CreateJsonSchema_FiltersDisallowedKeywords()
268280 "Char" : {
269281 "type": "string"
270282 }
271- },
272- "additionalProperties": false
283+ }
273284 }
274285 """ ) . RootElement ;
275286
@@ -341,14 +352,23 @@ public static void CreateFunctionJsonSchema_OptionalParameters(bool requireAllPr
341352 }
342353 """ ) . RootElement ;
343354
355+ AIJsonSchemaCreateOptions inferenceOptions = new ( )
356+ {
357+ TransformOptions = new ( )
358+ {
359+ RequireAllProperties = requireAllProperties ,
360+ MoveDefaultKeywordToDescription = requireAllProperties ,
361+ }
362+ } ;
363+
344364 AIFunction func = AIFunctionFactory . Create ( (
345365 [ Description ( "The city to get the weather for" ) ] string city ,
346366 [ Description ( "The unit to calculate the current temperature to" ) ] string unit = "celsius" ) => "sunny" ,
347367 new AIFunctionFactoryOptions
348368 {
349369 Name = "get_weather" ,
350370 Description = "Gets the current weather for a current location" ,
351- JsonSchemaCreateOptions = new AIJsonSchemaCreateOptions { RequireAllProperties = requireAllProperties }
371+ JsonSchemaCreateOptions = inferenceOptions
352372 } ) ;
353373
354374 Assert . NotNull ( func . UnderlyingMethod ) ;
@@ -358,7 +378,7 @@ public static void CreateFunctionJsonSchema_OptionalParameters(bool requireAllPr
358378 func . UnderlyingMethod ,
359379 title : func . Name ,
360380 description : func . Description ,
361- inferenceOptions : new AIJsonSchemaCreateOptions { RequireAllProperties = requireAllProperties } ) ;
381+ inferenceOptions : inferenceOptions ) ;
362382 AssertDeepEquals ( expected , resolvedSchema ) ;
363383 }
364384
@@ -423,7 +443,7 @@ public static void CreateJsonSchema_ValidateWithTestData(ITestData testData)
423443
424444 JsonTypeInfo typeInfo = options . GetTypeInfo ( testData . Type ) ;
425445 AIJsonSchemaCreateOptions ? createOptions = typeInfo . Properties . Any ( prop => prop . IsExtensionData )
426- ? new ( ) { DisallowAdditionalProperties = false } // Do not append additionalProperties: false to the schema if the type has extension data.
446+ ? new ( ) { TransformOptions = new ( ) { DisallowAdditionalProperties = false } } // Do not append additionalProperties: false to the schema if the type has extension data.
427447 : null ;
428448
429449 JsonElement schema = AIJsonUtilities . CreateJsonSchema ( testData . Type , serializerOptions : options , inferenceOptions : createOptions ) ;
@@ -706,6 +726,33 @@ public static void TransformJsonSchema_UseNullableKeyword()
706726 AssertDeepEquals ( expectedSchema , transformedSchema ) ;
707727 }
708728
729+ [ Fact ]
730+ public static void TransformJsonSchema_MoveDefaultKeywordToDescription ( )
731+ {
732+ JsonElement schema = JsonDocument . Parse ( """
733+ {
734+ "description": "My awesome schema",
735+ "type": "array",
736+ "default": [1,2,3]
737+ }
738+ """ ) . RootElement ;
739+
740+ JsonElement expectedSchema = JsonDocument . Parse ( """
741+ {
742+ "description": "My awesome schema (Default value: [1,2,3])",
743+ "type": "array"
744+ }
745+ """ ) . RootElement ;
746+
747+ AIJsonSchemaTransformOptions options = new ( )
748+ {
749+ MoveDefaultKeywordToDescription = true ,
750+ } ;
751+
752+ JsonElement transformedSchema = AIJsonUtilities . TransformSchema ( schema , options ) ;
753+ AssertDeepEquals ( expectedSchema , transformedSchema ) ;
754+ }
755+
709756 [ Theory ]
710757 [ MemberData ( nameof ( TestTypes . GetTestDataUsingAllValues ) , MemberType = typeof ( TestTypes ) ) ]
711758 public static void TransformJsonSchema_ValidateWithTestData ( ITestData testData )
@@ -718,7 +765,7 @@ public static void TransformJsonSchema_ValidateWithTestData(ITestData testData)
718765
719766 JsonTypeInfo typeInfo = options . GetTypeInfo ( testData . Type ) ;
720767 AIJsonSchemaCreateOptions ? createOptions = typeInfo . Properties . Any ( prop => prop . IsExtensionData )
721- ? new ( ) { DisallowAdditionalProperties = false } // Do not append additionalProperties: false to the schema if the type has extension data.
768+ ? new ( ) { TransformOptions = new ( ) { DisallowAdditionalProperties = false } } // Do not append additionalProperties: false to the schema if the type has extension data.
722769 : null ;
723770
724771 JsonElement schema = AIJsonUtilities . CreateJsonSchema ( testData . Type , serializerOptions : options , inferenceOptions : createOptions ) ;
0 commit comments