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
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using static Microsoft.Extensions.AI.Evaluation.Reporting.Storage.AzureStorageResponseCache;

namespace Microsoft.Extensions.AI.Evaluation.Reporting.JsonSerialization;

internal static partial class AzureStorageJsonUtilities
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Default matches the generated source naming convention.")]
internal static class Default
{
private static JsonSerializerOptions? _options;
internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: true);
internal static JsonTypeInfo<CacheEntry> CacheEntryTypeInfo => Options.GetTypeInfo<CacheEntry>();
internal static JsonTypeInfo<ScenarioRunResult> ScenarioRunResultTypeInfo => Options.GetTypeInfo<ScenarioRunResult>();
}

internal static class Compact
{
private static JsonSerializerOptions? _options;
internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: false);
internal static JsonTypeInfo<ScenarioRunResult> ScenarioRunResultTypeInfo => Options.GetTypeInfo<ScenarioRunResult>();
}

private static JsonTypeInfo<T> GetTypeInfo<T>(this JsonSerializerOptions options) => (JsonTypeInfo<T>)options.GetTypeInfo(typeof(T));

private static JsonSerializerOptions CreateJsonSerializerOptions(bool writeIndented)
{
var options = new JsonSerializerOptions(JsonContext.Default.Options)
{
WriteIndented = writeIndented,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
options.TypeInfoResolverChain.Add(AIJsonUtilities.DefaultOptions.TypeInfoResolver!);
options.MakeReadOnly();
return options;
}

[JsonSerializable(typeof(ScenarioRunResult))]
[JsonSerializable(typeof(CacheEntry))]
[JsonSourceGenerationOptions(
Converters = [
typeof(AzureStorageCamelCaseEnumConverter<EvaluationDiagnosticSeverity>),
typeof(AzureStorageCamelCaseEnumConverter<EvaluationRating>),
typeof(AzureStorageTimeSpanConverter)
],
WriteIndented = true,
IgnoreReadOnlyProperties = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
private sealed partial class JsonContext : JsonSerializerContext;

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static CacheEntry Read(
CacheEntry cacheEntry =
JsonSerializer.Deserialize(
content.Value.Content.ToMemory().Span,
AzureStorageSerializerContext.Default.CacheEntry)
AzureStorageJsonUtilities.Default.CacheEntryTypeInfo)
?? throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, fileClient.Name));

Expand All @@ -62,7 +62,7 @@ public static async Task<CacheEntry> ReadAsync(
CacheEntry cacheEntry =
await JsonSerializer.DeserializeAsync(
content.Value.Content.ToStream(),
AzureStorageSerializerContext.Default.CacheEntry,
AzureStorageJsonUtilities.Default.CacheEntryTypeInfo,
cancellationToken).ConfigureAwait(false)
?? throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, fileClient.Name));
Expand All @@ -76,7 +76,7 @@ public void Write(
{
MemoryStream stream = new();

JsonSerializer.Serialize(stream, this, AzureStorageSerializerContext.Default.CacheEntry);
JsonSerializer.Serialize(stream, this, AzureStorageJsonUtilities.Default.CacheEntryTypeInfo);

_ = stream.Seek(0, SeekOrigin.Begin);
_ = fileClient.Upload(stream, overwrite: true, cancellationToken);
Expand All @@ -91,7 +91,7 @@ public async Task WriteAsync(
await JsonSerializer.SerializeAsync(
stream,
this,
AzureStorageSerializerContext.Default.CacheEntry,
AzureStorageJsonUtilities.Default.CacheEntryTypeInfo,
cancellationToken).ConfigureAwait(false);

_ = stream.Seek(0, SeekOrigin.Begin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public async IAsyncEnumerable<ScenarioRunResult> ReadResultsAsync(

ScenarioRunResult? result = await JsonSerializer.DeserializeAsync(
content.Value.Content.ToStream(),
AzureStorageSerializerContext.Default.ScenarioRunResult,
AzureStorageJsonUtilities.Default.ScenarioRunResultTypeInfo,
cancellationToken).ConfigureAwait(false)
?? throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, fileClient.Name));
Expand Down Expand Up @@ -171,7 +171,7 @@ public async ValueTask WriteResultsAsync(
await JsonSerializer.SerializeAsync(
stream,
result,
AzureStorageSerializerContext.Default.ScenarioRunResult,
AzureStorageJsonUtilities.Default.ScenarioRunResultTypeInfo,
cancellationToken).ConfigureAwait(false);

_ = stream.Seek(0, SeekOrigin.Begin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public async ValueTask WriteReportAsync(
await JsonSerializer.SerializeAsync(
stream,
dataset,
SerializerContext.Compact.Dataset,
JsonUtilities.Compact.DatasetTypeInfo,
cancellationToken).ConfigureAwait(false);

#if NET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public async ValueTask WriteReportAsync(
await JsonSerializer.SerializeAsync(
stream,
dataset,
SerializerContext.Default.Dataset,
JsonUtilities.Default.DatasetTypeInfo,
cancellationToken).ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.AI.Evaluation.Reporting.Formats;
using static Microsoft.Extensions.AI.Evaluation.Reporting.Storage.DiskBasedResponseCache;

namespace Microsoft.Extensions.AI.Evaluation.Reporting.JsonSerialization;

internal static partial class JsonUtilities
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Default matches the generated source naming convention.")]
internal static class Default
{
private static JsonSerializerOptions? _options;
internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: true);
internal static JsonTypeInfo<Dataset> DatasetTypeInfo => Options.GetTypeInfo<Dataset>();
internal static JsonTypeInfo<CacheEntry> CacheEntryTypeInfo => Options.GetTypeInfo<CacheEntry>();
internal static JsonTypeInfo<CacheOptions> CacheOptionsTypeInfo => Options.GetTypeInfo<CacheOptions>();
internal static JsonTypeInfo<ScenarioRunResult> ScenarioRunResultTypeInfo => Options.GetTypeInfo<ScenarioRunResult>();
}

internal static class Compact
{
private static JsonSerializerOptions? _options;
internal static JsonSerializerOptions Options => _options ??= CreateJsonSerializerOptions(writeIndented: false);
internal static JsonTypeInfo<Dataset> DatasetTypeInfo => Options.GetTypeInfo<Dataset>();
internal static JsonTypeInfo<CacheEntry> CacheEntryTypeInfo => Options.GetTypeInfo<CacheEntry>();
internal static JsonTypeInfo<CacheOptions> CacheOptionsTypeInfo => Options.GetTypeInfo<CacheOptions>();
internal static JsonTypeInfo<ScenarioRunResult> ScenarioRunResultTypeInfo => Options.GetTypeInfo<ScenarioRunResult>();
}

private static JsonTypeInfo<T> GetTypeInfo<T>(this JsonSerializerOptions options) => (JsonTypeInfo<T>)options.GetTypeInfo(typeof(T));

private static JsonSerializerOptions CreateJsonSerializerOptions(bool writeIndented)
{
var options = new JsonSerializerOptions(JsonContext.Default.Options)
{
WriteIndented = writeIndented,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
options.TypeInfoResolverChain.Add(AIJsonUtilities.DefaultOptions.TypeInfoResolver!);
options.MakeReadOnly();
return options;
}

[JsonSerializable(typeof(EvaluationResult))]
[JsonSerializable(typeof(Dataset))]
[JsonSerializable(typeof(CacheEntry))]
[JsonSerializable(typeof(CacheOptions))]
[JsonSourceGenerationOptions(
Converters = [
typeof(CamelCaseEnumConverter<EvaluationDiagnosticSeverity>),
typeof(CamelCaseEnumConverter<EvaluationRating>),
typeof(CamelCaseEnumConverter<CacheMode>),
typeof(TimeSpanConverter)
],
WriteIndented = true,
IgnoreReadOnlyProperties = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
private sealed partial class JsonContext : JsonSerializerContext;

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static CacheEntry Read(string cacheEntryFilePath)
CacheEntry cacheEntry =
JsonSerializer.Deserialize(
cacheEntryFile,
SerializerContext.Default.CacheEntry) ??
JsonUtilities.Default.CacheEntryTypeInfo) ??
throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, cacheEntryFilePath));

Expand All @@ -56,7 +56,7 @@ public static async Task<CacheEntry> ReadAsync(
CacheEntry cacheEntry =
await JsonSerializer.DeserializeAsync(
cacheEntryFile,
SerializerContext.Default.CacheEntry,
JsonUtilities.Default.CacheEntryTypeInfo,
cancellationToken).ConfigureAwait(false) ??
throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, cacheEntryFilePath));
Expand All @@ -67,7 +67,7 @@ await JsonSerializer.DeserializeAsync(
public void Write(string cacheEntryFilePath)
{
using FileStream cacheEntryFile = File.Create(cacheEntryFilePath);
JsonSerializer.Serialize(cacheEntryFile, this, SerializerContext.Default.CacheEntry);
JsonSerializer.Serialize(cacheEntryFile, this, JsonUtilities.Default.CacheEntryTypeInfo);
}

public async Task WriteAsync(
Expand All @@ -78,7 +78,7 @@ public async Task WriteAsync(
await JsonSerializer.SerializeAsync(
cacheEntryFile,
this,
SerializerContext.Default.CacheEntry,
JsonUtilities.Default.CacheEntryTypeInfo,
cancellationToken).ConfigureAwait(false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static CacheOptions Read(string cacheOptionsFilePath)
CacheOptions cacheOptions =
JsonSerializer.Deserialize(
cacheOptionsFile,
SerializerContext.Default.CacheOptions) ??
JsonUtilities.Default.CacheOptionsTypeInfo) ??
throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, cacheOptionsFilePath));

Expand All @@ -61,7 +61,7 @@ public static async Task<CacheOptions> ReadAsync(
CacheOptions cacheOptions =
await JsonSerializer.DeserializeAsync<CacheOptions>(
cacheOptionsFile,
SerializerContext.Default.CacheOptions,
JsonUtilities.Default.CacheOptionsTypeInfo,
cancellationToken).ConfigureAwait(false) ??
throw new JsonException(
string.Format(CultureInfo.CurrentCulture, DeserializationFailedMessage, cacheOptionsFilePath));
Expand All @@ -72,7 +72,7 @@ await JsonSerializer.DeserializeAsync<CacheOptions>(
public void Write(string cacheOptionsFilePath)
{
using FileStream cacheOptionsFile = File.Create(cacheOptionsFilePath);
JsonSerializer.Serialize(cacheOptionsFile, this, SerializerContext.Default.CacheOptions);
JsonSerializer.Serialize(cacheOptionsFile, this, JsonUtilities.Default.CacheOptionsTypeInfo);
}

public async Task WriteAsync(
Expand All @@ -83,7 +83,7 @@ public async Task WriteAsync(
await JsonSerializer.SerializeAsync(
cacheOptionsFile,
this,
SerializerContext.Default.CacheOptions,
JsonUtilities.Default.CacheOptionsTypeInfo,
cancellationToken).ConfigureAwait(false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async IAsyncEnumerable<ScenarioRunResult> ReadResultsAsync(
ScenarioRunResult? result =
await JsonSerializer.DeserializeAsync<ScenarioRunResult>(
stream,
SerializerContext.Default.ScenarioRunResult,
JsonUtilities.Default.ScenarioRunResultTypeInfo,
cancellationToken).ConfigureAwait(false);

yield return result is null
Expand Down Expand Up @@ -101,7 +101,7 @@ public async ValueTask WriteResultsAsync(
await JsonSerializer.SerializeAsync(
stream,
result,
SerializerContext.Default.ScenarioRunResult,
JsonUtilities.Default.ScenarioRunResultTypeInfo,
cancellationToken).ConfigureAwait(false);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public void SerializeCacheEntry()
creation: DateTime.UtcNow,
expiration: DateTime.UtcNow.Add(TimeSpan.FromMinutes(5)));

string json = JsonSerializer.Serialize(entry, SerializerContext.Default.CacheEntry);
CacheEntry? deserialized = JsonSerializer.Deserialize<CacheEntry>(json, SerializerContext.Default.CacheEntry);
string json = JsonSerializer.Serialize(entry, JsonUtilities.Default.CacheEntryTypeInfo);
CacheEntry? deserialized = JsonSerializer.Deserialize<CacheEntry>(json, JsonUtilities.Default.CacheEntryTypeInfo);

Assert.NotNull(deserialized);
Assert.Equal(entry.ScenarioName, deserialized!.ScenarioName);
Expand All @@ -43,8 +43,8 @@ public void SerializeCacheEntryCompact()
creation: DateTime.UtcNow,
expiration: DateTime.UtcNow.Add(TimeSpan.FromMinutes(5)));

string json = JsonSerializer.Serialize(entry, SerializerContext.Compact.CacheEntry);
CacheEntry? deserialized = JsonSerializer.Deserialize<CacheEntry>(json, SerializerContext.Default.CacheEntry);
string json = JsonSerializer.Serialize(entry, JsonUtilities.Compact.CacheEntryTypeInfo);
CacheEntry? deserialized = JsonSerializer.Deserialize<CacheEntry>(json, JsonUtilities.Default.CacheEntryTypeInfo);

Assert.NotNull(deserialized);
Assert.Equal(entry.ScenarioName, deserialized!.ScenarioName);
Expand Down
Loading
Loading