diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index cea226f6fadf40..506abd2f3abd92 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -457,11 +457,13 @@ public JsonSerializerOptions(System.Text.Json.JsonSerializerOptions options) { } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Getting a converter for a type may require reflection which depends on unreferenced code.")] public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) { throw null; } public System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(System.Type type) { throw null; } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo() { throw null; } public void MakeReadOnly() { } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Populating unconfigured TypeInfoResolver properties with the reflection resolver requires runtime code generation.")] [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Populating unconfigured TypeInfoResolver properties with the reflection resolver requires unreferenced code.")] public void MakeReadOnly(bool populateMissingResolver) { } public bool TryGetTypeInfo(System.Type type, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.Serialization.Metadata.JsonTypeInfo? typeInfo) { throw null; } + public bool TryGetTypeInfo([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.Serialization.Metadata.JsonTypeInfo? typeInfo) { throw null; } } public enum JsonTokenType : byte { @@ -1152,6 +1154,7 @@ protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions? options) protected abstract System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } public System.Text.Json.JsonSerializerOptions Options { get { throw null; } } public abstract System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(System.Type type); + public System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo() { throw null; } System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options) { throw null; } } [System.FlagsAttribute] @@ -1270,6 +1273,9 @@ public DefaultJsonTypeInfoResolver() { } public partial interface IJsonTypeInfoResolver { System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options); +#if NET + System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo() { throw null; } +#endif } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class JsonCollectionInfoValues diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs index b13763ae624c18..a5ba60e9a65469 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs @@ -107,6 +107,14 @@ protected JsonSerializerContext(JsonSerializerOptions? options) /// The metadata for the specified type, or if the context has no metadata for the type. public abstract JsonTypeInfo? GetTypeInfo(Type type); + + /// + /// Returns a instance representing the given type. + /// + /// The type to fetch metadata about. + /// The metadata for the specified type, or if the context has no metadata for the type. + public JsonTypeInfo? GetTypeInfo() => (JsonTypeInfo?)GetTypeInfo(typeof(T)); + JsonTypeInfo? IJsonTypeInfoResolver.GetTypeInfo(Type type, JsonSerializerOptions options) { if (options != null && options != _options) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs index 8fda42bee9345f..6555a255f4b87b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Caching.cs @@ -64,6 +64,15 @@ public JsonTypeInfo GetTypeInfo(Type type) return GetTypeInfoInternal(type, resolveIfMutable: true); } + /// + /// Gets the contract metadata resolved by the current instance. + /// + /// The contract metadata resolved for . + /// + /// If the instance is locked for modification, the method will return a cached instance for the metadata. + /// + public JsonTypeInfo GetTypeInfo() => (JsonTypeInfo)GetTypeInfo(typeof(T)); + /// /// Tries to get the contract metadata resolved by the current instance. /// @@ -90,6 +99,27 @@ public bool TryGetTypeInfo(Type type, [NotNullWhen(true)] out JsonTypeInfo? type return typeInfo is not null; } + /// + /// Tries to get the contract metadata resolved by the current instance. + /// + /// The resolved contract metadata, or if no contract could be resolved. + /// if a contract for was found, or otherwise. + /// is not valid for serialization. + /// + /// If the instance is locked for modification, the method will return a cached instance for the metadata. + /// + public bool TryGetTypeInfo([NotNullWhen(true)] out JsonTypeInfo? typeInfo) + { + if (TryGetTypeInfo(typeof(T), out JsonTypeInfo? typeInfoOpt)) + { + typeInfo = (JsonTypeInfo)typeInfoOpt; + return true; + } + + typeInfo = null; + return false; + } + /// /// Same as GetTypeInfo but without validation and additional knobs. /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/IJsonTypeInfoResolver.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/IJsonTypeInfoResolver.cs index 4acabe53d731fa..bc397b5dfec35d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/IJsonTypeInfoResolver.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/IJsonTypeInfoResolver.cs @@ -18,5 +18,18 @@ public interface IJsonTypeInfoResolver /// or if no contract could be resolved. /// JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options); + +#if NET + /// + /// Resolves a contract for the requested type and options. + /// + /// Configuration used when resolving the metadata. + /// + /// A instance matching the requested type, + /// or if no contract could be resolved. + /// + JsonTypeInfo? GetTypeInfo(JsonSerializerOptions options) + => (JsonTypeInfo?)GetTypeInfo(typeof(T), options); +#endif } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index df27fc881b9229..6c4fdf394fd3f5 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs @@ -88,6 +88,14 @@ public static void IJsonTypeInfoResolver_GetTypeInfo_MetadataIsMutable() Assert.Equal(2, PersonJsonContext.Default.Person.Properties.Count); } + [Fact] + public static void TypeInfoIsSameAsGeneric() + { + var t1Info = (JsonTypeInfo)PersonJsonContext.Default.GetTypeInfo(typeof(Person)); + var t2Info = PersonJsonContext.Default.GetTypeInfo(); + Assert.Same(t1Info, t2Info); + } + [Fact] public static void VariousGenericsAreSupported() { @@ -215,9 +223,9 @@ public static void SupportsReservedLanguageKeywordsAsFields() var options = new JsonSerializerOptions { IncludeFields = true }; GreetingCardWithFields card = new() {@event = "Birthday", message = @"Happy Birthday!"}; - + byte[] utf8Json = JsonSerializer.SerializeToUtf8Bytes(card, GreetingCardWithFieldsJsonContext.Default.GreetingCardWithFields); - + card = JsonSerializer.Deserialize(utf8Json, GreetingCardWithFieldsJsonContext.Default.GreetingCardWithFields); Assert.Equal("Happy Birthday!", card.message); Assert.Equal("Birthday", card.@event); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs index 402ae6c8117d96..cc27a4c6750753 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/OptionsTests.cs @@ -674,6 +674,20 @@ public static void Options_JsonSerializerContext_DoesNotFallbackToReflection() Assert.Throws(() => JsonSerializer.Serialize(unsupportedValue, options)); } + [Fact] + public static void Options_GetTypeInfoGeneric() + { + var options = JsonContext.Default.Options; + var t1Info = (JsonTypeInfo)options.GetTypeInfo(typeof(WeatherForecastWithPOCOs)); + var t2Info = options.GetTypeInfo(); + Assert.Same(t1Info, t2Info); + + Assert.True(options.TryGetTypeInfo(typeof(WeatherForecastWithPOCOs), out JsonTypeInfo? t3Info)); + Assert.True(options.TryGetTypeInfo(out var t4Info)); + Assert.Same(t1Info, t3Info); + Assert.Same(t3Info, t4Info); + } + [Fact] public static void JsonSerializer_IsReflectionEnabledByDefault_DefaultsToTrue() {