Skip to content
Merged
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
14 changes: 4 additions & 10 deletions src/Extensions/ToolJsonOptions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.AI;

namespace Devlooped.Extensions.AI;

Expand All @@ -16,19 +15,14 @@ public static class ToolJsonOptions
/// <summary>
/// Default <see cref="JsonSerializerOptions"/> for function calling and tools.
/// </summary>
public static JsonSerializerOptions Default { get; } = new(JsonSerializerDefaults.Web)
public static JsonSerializerOptions Default { get; } = new(AIJsonUtilities.DefaultOptions)
{
Converters =
{
new AdditionalPropertiesDictionaryConverter(),
new JsonStringEnumConverter(),
},
DefaultIgnoreCondition =
JsonIgnoreCondition.WhenWritingDefault |
JsonIgnoreCondition.WhenWritingNull,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
WriteIndented = Debugger.IsAttached,
TypeInfoResolver = new TypeInjectingResolver(new DefaultJsonTypeInfoResolver())
WriteIndented = Debugger.IsAttached || AIJsonUtilities.DefaultOptions.WriteIndented,
TypeInfoResolver = new TypeInjectingResolver(AIJsonUtilities.DefaultOptions.TypeInfoResolverChain)
};
}
11 changes: 7 additions & 4 deletions src/Extensions/TypeInjectingResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public static JsonSerializerOptions WithTypeInjection(this JsonSerializerOptions
if (options.IsReadOnly)
options = new(options);

options.TypeInfoResolver = new TypeInjectingResolver(
JsonTypeInfoResolver.Combine([.. options.TypeInfoResolverChain]));
options.TypeInfoResolver = new TypeInjectingResolver(options.TypeInfoResolverChain);

return options;
}
Expand All @@ -29,12 +28,15 @@ public static JsonSerializerOptions WithTypeInjection(this JsonSerializerOptions
/// A custom <see cref="IJsonTypeInfoResolver"/> that injects a $type property into object types
/// so they can be automatically distinguished during deserialization or inspection.
/// </summary>
public class TypeInjectingResolver(IJsonTypeInfoResolver inner) : IJsonTypeInfoResolver
public class TypeInjectingResolver(IList<IJsonTypeInfoResolver> chain) : IJsonTypeInfoResolver
{
readonly IJsonTypeInfoResolver resolver = JsonTypeInfoResolver.Combine([.. chain]);

/// <inheritdoc />
public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options)
{
var info = inner.GetTypeInfo(type, options);
var info = resolver.GetTypeInfo(type, options);

// The $type would already be present for polymorphic serialization.
if (info?.Kind == JsonTypeInfoKind.Object && !info.Properties.Any(x => x.Name == "$type"))
{
Expand All @@ -43,6 +45,7 @@ public class TypeInjectingResolver(IJsonTypeInfoResolver inner) : IJsonTypeInfoR
prop.Order = -1000; // Ensure it is serialized first
info.Properties.Add(prop);
}

return info;
}
}
Loading