using System.Text.Json; using System.Text.Json.Serialization; namespace AIStudio.Provider.OpenAI; /// /// Custom JSON converter for the annotation class to handle polymorphic deserialization. /// /// /// We use this converter for chat completion API and responses API annotation deserialization. /// public sealed class AnnotationConverter : JsonConverter { public override Annotation? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; if (!root.TryGetProperty("type", out var typeElement)) return null; var type = typeElement.GetString(); var rawText = root.GetRawText(); Annotation? annotation; switch (type) { case "url_citation": // Let's check the responses API data type first: var responsesAnnotation = JsonSerializer.Deserialize(rawText, options); // If it fails, let's try the chat completion API data type: if(responsesAnnotation is null || string.IsNullOrWhiteSpace(responsesAnnotation.Title) || string.IsNullOrWhiteSpace(responsesAnnotation.URL)) { // Try chat completion API data type: var chatCompletionAnnotation = JsonSerializer.Deserialize(rawText, options); // If both fail, we return the unknown type: if(chatCompletionAnnotation is null) annotation = new AnnotatingUnknown(type); else annotation = chatCompletionAnnotation; } else annotation = responsesAnnotation; break; default: annotation = new AnnotatingUnknown(type ?? "unknown"); break; } return annotation; } public override void Write(Utf8JsonWriter writer, Annotation value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, value.GetType(), options); } }