Skip to content
Draft
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
6 changes: 6 additions & 0 deletions src/libraries/System.Text.Json/ref/System.Text.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> GetTypeInfo<T>() { 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<T>([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Text.Json.Serialization.Metadata.JsonTypeInfo<T>? typeInfo) { throw null; }
}
public enum JsonTokenType : byte
{
Expand Down Expand Up @@ -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<T> GetTypeInfo<T>() { 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]
Expand Down Expand Up @@ -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<T> GetTypeInfo<T>() { throw null; }
#endif
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public sealed partial class JsonCollectionInfoValues<TCollection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ protected JsonSerializerContext(JsonSerializerOptions? options)
/// <returns>The metadata for the specified type, or <see langword="null" /> if the context has no metadata for the type.</returns>
public abstract JsonTypeInfo? GetTypeInfo(Type type);


/// <summary>
/// Returns a <see cref="JsonTypeInfo{T}"/> instance representing the given type.
/// </summary>
/// <typeparam name="T">The type to fetch metadata about.</typeparam>
/// <returns>The metadata for the specified type, or <see langword="null" /> if the context has no metadata for the type.</returns>
public JsonTypeInfo<T>? GetTypeInfo<T>() => (JsonTypeInfo<T>?)GetTypeInfo(typeof(T));

JsonTypeInfo? IJsonTypeInfoResolver.GetTypeInfo(Type type, JsonSerializerOptions options)
{
if (options != null && options != _options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ public JsonTypeInfo GetTypeInfo(Type type)
return GetTypeInfoInternal(type, resolveIfMutable: true);
}

/// <summary>
/// Gets the <see cref="JsonTypeInfo{T}"/> contract metadata resolved by the current <see cref="JsonSerializerOptions"/> instance.
/// </summary>
/// <returns>The contract metadata resolved for <typeparamref name="T"/>.</returns>
/// <remarks>
/// If the <see cref="JsonSerializerOptions"/> instance is locked for modification, the method will return a cached instance for the metadata.
/// </remarks>
public JsonTypeInfo<T> GetTypeInfo<T>() => (JsonTypeInfo<T>)GetTypeInfo(typeof(T));

/// <summary>
/// Tries to get the <see cref="JsonTypeInfo"/> contract metadata resolved by the current <see cref="JsonSerializerOptions"/> instance.
/// </summary>
Expand All @@ -90,6 +99,27 @@ public bool TryGetTypeInfo(Type type, [NotNullWhen(true)] out JsonTypeInfo? type
return typeInfo is not null;
}

/// <summary>
/// Tries to get the <see cref="JsonTypeInfo{T}"/> contract metadata resolved by the current <see cref="JsonSerializerOptions"/> instance.
/// </summary>
/// <param name="typeInfo">The resolved contract metadata, or <see langword="null" /> if no contract could be resolved.</param>
/// <returns><see langword="true"/> if a contract for <typeparamref name="T"/> was found, or <see langword="false"/> otherwise.</returns>
/// <exception cref="ArgumentException"><typeparamref name="T"/> is not valid for serialization.</exception>
/// <remarks>
/// If the <see cref="JsonSerializerOptions"/> instance is locked for modification, the method will return a cached instance for the metadata.
/// </remarks>
public bool TryGetTypeInfo<T>([NotNullWhen(true)] out JsonTypeInfo<T>? typeInfo)
{
if (TryGetTypeInfo(typeof(T), out JsonTypeInfo? typeInfoOpt))
{
typeInfo = (JsonTypeInfo<T>)typeInfoOpt;
return true;
}

typeInfo = null;
return false;
}

/// <summary>
/// Same as GetTypeInfo but without validation and additional knobs.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,18 @@ public interface IJsonTypeInfoResolver
/// or <see langword="null"/> if no contract could be resolved.
/// </returns>
JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options);

#if NET
/// <summary>
/// Resolves a <see cref="JsonTypeInfo{T}"/> contract for the requested type and options.
/// </summary>
/// <param name="options">Configuration used when resolving the metadata.</param>
/// <returns>
/// A <see cref="JsonTypeInfo{T}"/> instance matching the requested type,
/// or <see langword="null"/> if no contract could be resolved.
/// </returns>
JsonTypeInfo<T>? GetTypeInfo<T>(JsonSerializerOptions options)
=> (JsonTypeInfo<T>?)GetTypeInfo(typeof(T), options);
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Person>)PersonJsonContext.Default.GetTypeInfo(typeof(Person));
var t2Info = PersonJsonContext.Default.GetTypeInfo<Person>();
Assert.Same(t1Info, t2Info);
}

[Fact]
public static void VariousGenericsAreSupported()
{
Expand Down Expand Up @@ -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<GreetingCardWithFields>(utf8Json, GreetingCardWithFieldsJsonContext.Default.GreetingCardWithFields);
Assert.Equal("Happy Birthday!", card.message);
Assert.Equal("Birthday", card.@event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,20 @@ public static void Options_JsonSerializerContext_DoesNotFallbackToReflection()
Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(unsupportedValue, options));
}

[Fact]
public static void Options_GetTypeInfoGeneric()
{
var options = JsonContext.Default.Options;
var t1Info = (JsonTypeInfo<WeatherForecastWithPOCOs>)options.GetTypeInfo(typeof(WeatherForecastWithPOCOs));
var t2Info = options.GetTypeInfo<WeatherForecastWithPOCOs>();
Assert.Same(t1Info, t2Info);

Assert.True(options.TryGetTypeInfo(typeof(WeatherForecastWithPOCOs), out JsonTypeInfo? t3Info));
Assert.True(options.TryGetTypeInfo<WeatherForecastWithPOCOs>(out var t4Info));
Assert.Same(t1Info, t3Info);
Assert.Same(t3Info, t4Info);
}

[Fact]
public static void JsonSerializer_IsReflectionEnabledByDefault_DefaultsToTrue()
{
Expand Down
Loading