mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-05 06:07:21 +00:00
Generated the JSON contracts of providers, the runtime, and services at compile time (#1150)
This commit is contained in:
1 parent
e954881fda
commit
24e3c22db3
140 files changed
+1415
-292
No files matched your search
@@ -7,11 +7,12 @@ namespace AIStudio.Tests.Serialization;
|
||||
/// Checks that a property missing in the JSON keeps the value a new object starts with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Files written by an older version of AI Studio lack every property added since. Reading them has to give
|
||||
/// those properties their defaults, as a new object has them, e.g., a sub-object of the settings instead of
|
||||
/// null. Source generation in .NET 10 breaks this for init-only properties: it sets them all while creating
|
||||
/// the object, and a property missing in the JSON gets the default of its type instead (dotnet/runtime#84484).
|
||||
/// Hence, the types AI Studio stores use set instead of init.<br/><br/>
|
||||
/// Files written by an older version of AI Studio lack every property added since, and an answer of a
|
||||
/// provider, of the runtime, or of a service leaves out whatever it has nothing to say about. Reading them has
|
||||
/// to give those properties their defaults, as a new object has them, e.g., a sub-object of the settings
|
||||
/// instead of null. Source generation in .NET 10 breaks this for init-only properties: it sets them all while
|
||||
/// creating the object, and a property missing in the JSON gets the default of its type instead
|
||||
/// (dotnet/runtime#84484). Hence, the types AI Studio reads use set instead of init.<br/><br/>
|
||||
///
|
||||
/// A new object is created the way reflection creates it: with its parameterless constructor, or, for a
|
||||
/// struct, as the default of the struct. Source generation passes the values of a positional record struct
|
||||
@@ -21,6 +22,9 @@ namespace AIStudio.Tests.Serialization;
|
||||
public sealed class JsonDefaultsTests
|
||||
{
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.Stored))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ProviderAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.RuntimeAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ServiceAnswers))]
|
||||
public void AnEmptyObjectGetsTheDefaultsOfANewOne(JsonTestRoot root)
|
||||
{
|
||||
var baseline = JsonReflectionBaseline.Of(root.Options);
|
||||
@@ -60,7 +64,14 @@ public sealed class JsonDefaultsTests
|
||||
Assert.That(failures, Is.Empty);
|
||||
}
|
||||
|
||||
private static string ValueAsJson(JsonPropertyInfo property, object instance, JsonSerializerOptions options) => JsonSerializer.Serialize(property.Get!(instance), property.PropertyType, options);
|
||||
private static string ValueAsJson(JsonPropertyInfo property, object instance, JsonSerializerOptions options) => AsJson(property.Get!(instance), property.PropertyType, options);
|
||||
|
||||
private static string DefaultAsJson(Type type, JsonSerializerOptions options) => type.IsValueType ? JsonSerializer.Serialize(Activator.CreateInstance(type), type, options) : "null";
|
||||
private static string DefaultAsJson(Type type, JsonSerializerOptions options) => type.IsValueType ? AsJson(Activator.CreateInstance(type), type, options) : "null";
|
||||
|
||||
private static string AsJson(object? value, Type type, JsonSerializerOptions options) => value switch
|
||||
{
|
||||
// The default of a JsonElement holds no JSON at all, so it cannot be written:
|
||||
JsonElement { ValueKind: JsonValueKind.Undefined } => "no JSON",
|
||||
_ => JsonSerializer.Serialize(value, type, options),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user