Skip to content

Commit b75358d

Browse files
Ensure the type keyword is included when generating schemas for nullable enums. (#6440)
1 parent 8ea542c commit b75358d

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.Create.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ JsonNode TransformSchemaNode(JsonSchemaExporterContext schemaExporterContext, Js
274274
objSchema.InsertAtStart(TypePropertyName, "string");
275275
}
276276

277+
// Include the type keyword in nullable enum types
278+
if (Nullable.GetUnderlyingType(ctx.TypeInfo.Type)?.IsEnum is true && objSchema.ContainsKey(EnumPropertyName) && !objSchema.ContainsKey(TypePropertyName))
279+
{
280+
objSchema.InsertAtStart(TypePropertyName, new JsonArray { (JsonNode)"string", (JsonNode)"null" });
281+
}
282+
277283
// Filter potentially disallowed keywords.
278284
foreach (string keyword in _schemaKeywordsDisallowedByAIVendors)
279285
{

test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Utilities/AIJsonUtilitiesTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,20 @@ public static void CreateJsonSchema_AcceptsOptionsWithoutResolver()
477477
Assert.Same(options.TypeInfoResolver, AIJsonUtilities.DefaultOptions.TypeInfoResolver);
478478
}
479479

480+
[Fact]
481+
public static void CreateJsonSchema_NullableEnum_IncludesTypeKeyword()
482+
{
483+
JsonElement expectedSchema = JsonDocument.Parse("""
484+
{
485+
"type": ["string", "null"],
486+
"enum": ["A", "B", null]
487+
}
488+
""").RootElement;
489+
490+
JsonElement schema = AIJsonUtilities.CreateJsonSchema(typeof(MyEnumValue?), serializerOptions: JsonContext.Default.Options);
491+
AssertDeepEquals(expectedSchema, schema);
492+
}
493+
480494
[Fact]
481495
public static void AddAIContentType_DerivedAIContent()
482496
{
@@ -846,6 +860,7 @@ private class DerivedAIContent : AIContent
846860
[JsonSerializable(typeof(DerivedAIContent))]
847861
[JsonSerializable(typeof(MyPoco))]
848862
[JsonSerializable(typeof(PocoWithTypesWithOpenAIUnsupportedKeywords))]
863+
[JsonSerializable(typeof(MyEnumValue?))]
849864
private partial class JsonContext : JsonSerializerContext;
850865

851866
private static bool DeepEquals(JsonElement element1, JsonElement element2)

0 commit comments

Comments
 (0)