.Net: fix function enum argument deserialization#14001
Conversation
There was a problem hiding this comment.
Pull request overview
Aligns default tool-argument deserialization with the JSON options used for tool schema generation so string-enum values (including nested enums) deserialize correctly when callers don’t provide JsonSerializerOptions.
Changes:
- Reuses
KernelJsonSchemaBuilderdefaultJsonSerializerOptionsas the fallback inKernelFunctionFromMethod.TryToDeserializeValuewhen no options are provided. - Exposes an internal accessor for the schema builder’s default options (with AOT annotations preserved).
- Adds a unit test covering string-enum deserialization with default options.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs | Uses an “effective” JsonSerializerOptions fallback so enums deserialize as strings by default. |
| dotnet/src/InternalUtilities/src/Schema/KernelJsonSchemaBuilder.cs | Adds an internal accessor for the schema builder’s cached default serializer options. |
| dotnet/src/SemanticKernel.UnitTests/Functions/KernelFunctionFromMethodTests1.cs | Adds a regression test validating default string-enum argument deserialization. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var func = KernelFunctionFactory.CreateFromMethod((Reminder[] param) => { actualArgValue = param; }); | ||
|
|
||
| // Act | ||
| var res = await func.InvokeAsync(this._kernel, new() { ["param"] = jsonString }); |
| [RequiresUnreferencedCode("Uses JsonStringEnumConverter and DefaultJsonTypeInfoResolver classes, making it incompatible with AOT scenarios.")] | ||
| [RequiresDynamicCode("Uses JsonStringEnumConverter and DefaultJsonTypeInfoResolver classes, making it incompatible with AOT scenarios.")] | ||
| internal static JsonSerializerOptions GetDefaultOptionsForSerialization() => GetDefaultOptions(); |
afc3049 to
a1450a2
Compare
a1450a2 to
c4c6ec0
Compare
|
Addressed both review comments and rebased onto current main. The unused local in the new regression test now uses an explicit discard, and the shared fallback options accessor is now named GetDefaultJsonSerializerOptions() so it no longer reads as serialization-only.\n\nValidation on Windows:\n\n |
Summary
Fixes #13589.
KernelJsonSchemaBuilderbuilds function parameter schemas with the default schema options, including string enum handling. When a tool call comes back as JSON and no customJsonSerializerOptionsare supplied,KernelFunctionFromMethod.TryToDeserializeValuewas using plainSystem.Text.Jsondefaults instead, so nested enum values like"hours"failed to bind.This patch reuses the schema builder's default options as the fallback for argument deserialization, while preserving caller-provided serializer options when they exist.
I also checked the previous PR for this issue (#13623). It was closed by the author due inactivity rather than rejected, so this is a fresh patch with a smaller test surface.
Validation