33
44using System ;
55using System . Collections . Generic ;
6+ using System . Diagnostics . CodeAnalysis ;
67using System . Reflection ;
78using System . Runtime . CompilerServices ;
89using System . Text ;
910using System . Text . Json ;
1011using System . Text . Json . Serialization ;
12+ using System . Text . Json . Serialization . Metadata ;
1113using System . Threading ;
1214using System . Threading . Tasks ;
1315using Microsoft . Shared . Diagnostics ;
@@ -587,10 +589,9 @@ private sealed class OpenAIChatToolJson
587589 string ? result = resultContent . Result as string ;
588590 if ( result is null && resultContent . Result is not null )
589591 {
590- JsonSerializerOptions options = ToolCallJsonSerializerOptions ?? JsonContext . Default . Options ;
591592 try
592593 {
593- result = JsonSerializer . Serialize ( resultContent . Result , options . GetTypeInfo ( typeof ( object ) ) ) ;
594+ result = JsonSerializer . Serialize ( resultContent . Result , JsonContext . GetTypeInfo ( typeof ( object ) , ToolCallJsonSerializerOptions ) ) ;
594595 }
595596 catch ( NotSupportedException )
596597 {
@@ -617,7 +618,9 @@ private sealed class OpenAIChatToolJson
617618 ChatToolCall . CreateFunctionToolCall (
618619 callRequest . CallId ,
619620 callRequest . Name ,
620- BinaryData . FromObjectAsJson ( callRequest . Arguments , ToolCallJsonSerializerOptions ) ) ) ;
621+ new ( JsonSerializer . SerializeToUtf8Bytes (
622+ callRequest . Arguments ,
623+ JsonContext . GetTypeInfo ( typeof ( IDictionary < string , object ? > ) , ToolCallJsonSerializerOptions ) ) ) ) ) ;
621624 }
622625 }
623626
@@ -670,8 +673,53 @@ private static FunctionCallContent ParseCallContentFromBinaryData(BinaryData ut8
670673 argumentParser : static json => JsonSerializer . Deserialize ( json , JsonContext . Default . IDictionaryStringObject ) ! ) ;
671674
672675 /// <summary>Source-generated JSON type information.</summary>
676+ [ JsonSourceGenerationOptions ( JsonSerializerDefaults . Web ,
677+ UseStringEnumConverter = true ,
678+ DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull ,
679+ WriteIndented = true ) ]
673680 [ JsonSerializable ( typeof ( OpenAIChatToolJson ) ) ]
674681 [ JsonSerializable ( typeof ( IDictionary < string , object ? > ) ) ]
675682 [ JsonSerializable ( typeof ( JsonElement ) ) ]
676- private sealed partial class JsonContext : JsonSerializerContext ;
683+ private sealed partial class JsonContext : JsonSerializerContext
684+ {
685+ /// <summary>Gets the <see cref="JsonSerializerOptions"/> singleton used as the default in JSON serialization operations.</summary>
686+ private static readonly JsonSerializerOptions _defaultToolJsonOptions = CreateDefaultToolJsonOptions ( ) ;
687+
688+ /// <summary>Gets JSON type information for the specified type.</summary>
689+ /// <remarks>
690+ /// This first tries to get the type information from <paramref name="firstOptions"/>,
691+ /// falling back to <see cref="_defaultToolJsonOptions"/> if it can't.
692+ /// </remarks>
693+ public static JsonTypeInfo GetTypeInfo ( Type type , JsonSerializerOptions ? firstOptions ) =>
694+ firstOptions ? . TryGetTypeInfo ( type , out JsonTypeInfo ? info ) is true ?
695+ info :
696+ _defaultToolJsonOptions . GetTypeInfo ( type ) ;
697+
698+ /// <summary>Creates the default <see cref="JsonSerializerOptions"/> to use for serialization-related operations.</summary>
699+ [ UnconditionalSuppressMessage ( "AotAnalysis" , "IL3050" , Justification = "DefaultJsonTypeInfoResolver is only used when reflection-based serialization is enabled" ) ]
700+ [ UnconditionalSuppressMessage ( "ReflectionAnalysis" , "IL2026" , Justification = "DefaultJsonTypeInfoResolver is only used when reflection-based serialization is enabled" ) ]
701+ private static JsonSerializerOptions CreateDefaultToolJsonOptions ( )
702+ {
703+ // If reflection-based serialization is enabled by default, use it, as it's the most permissive in terms of what it can serialize,
704+ // and we want to be flexible in terms of what can be put into the various collections in the object model.
705+ // Otherwise, use the source-generated options to enable trimming and Native AOT.
706+
707+ if ( JsonSerializer . IsReflectionEnabledByDefault )
708+ {
709+ // Keep in sync with the JsonSourceGenerationOptions attribute on JsonContext above.
710+ JsonSerializerOptions options = new ( JsonSerializerDefaults . Web )
711+ {
712+ TypeInfoResolver = new DefaultJsonTypeInfoResolver ( ) ,
713+ Converters = { new JsonStringEnumConverter ( ) } ,
714+ DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull ,
715+ WriteIndented = true ,
716+ } ;
717+
718+ options . MakeReadOnly ( ) ;
719+ return options ;
720+ }
721+
722+ return Default . Options ;
723+ }
724+ }
677725}
0 commit comments