Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ private static JsonSerializerOptions GetDefaultOptions()
{
JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver(),
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { ExcludeReadOnlyProperties }
},
Converters = { new JsonStringEnumConverter() },
};
options.MakeReadOnly();
Expand All @@ -76,4 +79,19 @@ private static JsonSerializerOptions GetDefaultOptions()

return s_options;
}

private static void ExcludeReadOnlyProperties(JsonTypeInfo typeInfo)
{
if (typeInfo.Kind != JsonTypeInfoKind.Object) return;

for (int i = 0; i < typeInfo.Properties.Count; i++)
{
var property = typeInfo.Properties[i];

if (property.Set == null)
{
typeInfo.Properties.RemoveAt(i--);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.

using System;
using System.ComponentModel;
using System.Text;
using System.Text.Json;
using Microsoft.SemanticKernel;
Expand Down Expand Up @@ -91,6 +92,39 @@ public void ItThrowsOnInvalidJson()
Assert.ThrowsAny<JsonException>(() => KernelJsonSchema.Parse(Encoding.UTF8.GetBytes(InvalidJsonSchema)));
}

[Fact]
public void ItShouldExcludeReadOnlyPropertiesFromSchema()
{
var function = KernelFunctionFactory.CreateFromMethod(
(MyComplexType input) => { },
"TestFunction");

var schema = function.Metadata.Parameters[0].Schema;
var jsonSchemaString = schema?.ToString();

Assert.NotNull(jsonSchemaString);
Assert.Contains("Status", jsonSchemaString);
Assert.DoesNotContain("Derived", jsonSchemaString);
}

/// <summary>
/// A helper class specific to this test case.
/// Used to verify that read-only properties are ignored by the schema generator.
/// </summary>
private sealed class MyComplexType
{
[Description("The current status of the user account")]
public MyStatus Status { get; set; }

public string Derived => $"Status is {Status}";
}

private enum MyStatus
{
Active,
Inactive
}

// TODO: KernelJsonSchema currently validates that the input is valid JSON but not that it's valid JSON schema.
//[Theory]
//[InlineData("{ \"type\":\"invalid\" }")]
Expand Down