Skip to content

.Net: fix function enum argument deserialization#14001

Open
he-yufeng wants to merge 2 commits into
microsoft:mainfrom
he-yufeng:fix/function-enum-json-options
Open

.Net: fix function enum argument deserialization#14001
he-yufeng wants to merge 2 commits into
microsoft:mainfrom
he-yufeng:fix/function-enum-json-options

Conversation

@he-yufeng
Copy link
Copy Markdown

Summary

Fixes #13589.

KernelJsonSchemaBuilder builds function parameter schemas with the default schema options, including string enum handling. When a tool call comes back as JSON and no custom JsonSerializerOptions are supplied, KernelFunctionFromMethod.TryToDeserializeValue was using plain System.Text.Json defaults 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

dotnet test dotnet\src\SemanticKernel.UnitTests\SemanticKernel.UnitTests.csproj --framework net10.0 --filter "FullyQualifiedName~KernelFunctionFromMethodTests1" --no-restore --logger "console;verbosity=minimal"
# passed: 75

dotnet format dotnet\src\SemanticKernel.UnitTests\SemanticKernel.UnitTests.csproj --include dotnet/src/InternalUtilities/src/Schema/KernelJsonSchemaBuilder.cs dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs dotnet/src/SemanticKernel.UnitTests/Functions/KernelFunctionFromMethodTests1.cs --verify-no-changes --no-restore

git diff --check

Copilot AI review requested due to automatic review settings May 12, 2026 19:40
@he-yufeng he-yufeng requested a review from a team as a code owner May 12, 2026 19:40
@moonbox3 moonbox3 added .NET Issue or Pull requests regarding .NET code kernel Issues or pull requests impacting the core kernel labels May 12, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 91% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Design Approach


Automated review by he-yufeng's agents

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 KernelJsonSchemaBuilder default JsonSerializerOptions as the fallback in KernelFunctionFromMethod.TryToDeserializeValue when 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 });
Comment on lines +29 to +31
[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();
@he-yufeng he-yufeng force-pushed the fix/function-enum-json-options branch from afc3049 to a1450a2 Compare May 13, 2026 10:40
@he-yufeng he-yufeng force-pushed the fix/function-enum-json-options branch from a1450a2 to c4c6ec0 Compare May 14, 2026 14:18
@he-yufeng
Copy link
Copy Markdown
Author

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\npowershell\ndotnet build dotnet\\src\\SemanticKernel.Core\\SemanticKernel.Core.csproj --no-restore\ndotnet build dotnet\\src\\SemanticKernel.UnitTests\\SemanticKernel.UnitTests.csproj --no-restore --no-incremental\ndotnet test dotnet\\src\\SemanticKernel.UnitTests\\SemanticKernel.UnitTests.csproj --no-restore --filter FullyQualifiedName~ItCanDeserializeStringEnumsWithDefaultJsonOptionsAsync --no-build\ndotnet format dotnet\\src\\SemanticKernel.Core\\SemanticKernel.Core.csproj --verify-no-changes --no-restore --include dotnet\\src\\InternalUtilities\\src\\Schema\\KernelJsonSchemaBuilder.cs dotnet\\src\\SemanticKernel.Core\\Functions\\KernelFunctionFromMethod.cs\ndotnet format dotnet\\src\\SemanticKernel.UnitTests\\SemanticKernel.UnitTests.csproj --verify-no-changes --no-restore --include dotnet\\src\\SemanticKernel.UnitTests\\Functions\\KernelFunctionFromMethodTests1.cs\ngit diff --check\n\n\nResult: core build passed, unit-test project build passed, targeted test passed, targeted format checks passed, diff check passed. Note: solution-wide dotnet format dotnet\SK-dotnet.slnx --no-restore is not usable in this checkout without restoring unrelated projects; it fails before formatting the touched files because many unrelated projects are unloaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kernel Issues or pull requests impacting the core kernel .NET Issue or Pull requests regarding .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.Net: Bug: JSON serializer options don't match between tool schema and tool calls, causing enum parameters to fail.

3 participants