diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs index 988bd0147bd0b6..ea261dfd45892e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs @@ -26,7 +26,12 @@ namespace System.Diagnostics.CodeAnalysis AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method, Inherited = false)] - public sealed class DynamicallyAccessedMembersAttribute : Attribute +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DynamicallyAccessedMembersAttribute : Attribute { /// /// Initializes a new instance of the class 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 bcc2ffec78ceed..df7879f7e05012 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -185,6 +185,29 @@ public partial struct JsonReaderState } public static partial class JsonSerializer { +#if NETCOREAPP + private const System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MembersAccessedOnRead = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties; + private const System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MembersAccessedOnWrite = System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties; + public static object? Deserialize(System.ReadOnlySpan utf8Json, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize(string json, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static object? Deserialize(ref System.Text.Json.Utf8JsonReader reader, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask DeserializeAsync<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] TValue>(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] TValue>(System.ReadOnlySpan utf8Json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] TValue>(string json, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNull] + public static TValue Deserialize<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnRead)] TValue>(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static string Serialize(object? value, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object? value, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { } + public static System.Threading.Tasks.Task SerializeAsync(System.IO.Stream utf8Json, object? value, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SerializeAsync<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] TValue>(System.IO.Stream utf8Json, TValue value, System.Text.Json.JsonSerializerOptions? options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static byte[] SerializeToUtf8Bytes(object? value, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] System.Type inputType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static byte[] SerializeToUtf8Bytes<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] TValue>(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } + public static void Serialize<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] TValue>(System.Text.Json.Utf8JsonWriter writer, TValue value, System.Text.Json.JsonSerializerOptions? options = null) { } + public static string Serialize<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(MembersAccessedOnWrite)] TValue>(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } +#else public static object? Deserialize(System.ReadOnlySpan utf8Json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static object? Deserialize(string json, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static object? Deserialize(ref System.Text.Json.Utf8JsonReader reader, System.Type returnType, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } @@ -204,6 +227,7 @@ public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object? val public static byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } public static void Serialize(System.Text.Json.Utf8JsonWriter writer, TValue value, System.Text.Json.JsonSerializerOptions? options = null) { } public static string Serialize(TValue value, System.Text.Json.JsonSerializerOptions? options = null) { throw null; } +#endif } public sealed partial class JsonSerializerOptions { @@ -483,8 +507,14 @@ internal JsonConverter() { } public partial class JsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute { protected JsonConverterAttribute() { } +#if NETCOREAPP + public JsonConverterAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type converterType) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public System.Type? ConverterType { get { throw null; } } +#else public JsonConverterAttribute(System.Type converterType) { } public System.Type? ConverterType { get { throw null; } } +#endif public virtual System.Text.Json.Serialization.JsonConverter? CreateConverter(System.Type typeToConvert) { throw null; } } public abstract partial class JsonConverterFactory : System.Text.Json.Serialization.JsonConverter diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 5d8e706a2aa4bc..2cd2e121005e0b 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -238,6 +238,7 @@ + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs index 51095cd5c7b125..32a380fee0af9f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Attributes/JsonConverterAttribute.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics.CodeAnalysis; + namespace System.Text.Json.Serialization { /// @@ -21,7 +23,7 @@ public class JsonConverterAttribute : JsonAttribute /// Initializes a new instance of with the specified converter type. /// /// The type of the converter. - public JsonConverterAttribute(Type converterType) + public JsonConverterAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type converterType) { ConverterType = converterType; } @@ -34,6 +36,7 @@ protected JsonConverterAttribute() { } /// /// The type of the converter to create, or null if should be used to obtain the converter. /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] public Type? ConverterType { get; private set; } /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs index 7b1cdd130f50d6..7924b6d30563ee 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs @@ -6,7 +6,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Text.Json.Serialization.Converters @@ -25,23 +24,6 @@ public override bool CanConvert(Type typeToConvert) return typeof(IEnumerable).IsAssignableFrom(typeToConvert); } - [DynamicDependency("#ctor", typeof(ArrayConverter<,>))] - [DynamicDependency("#ctor", typeof(ConcurrentQueueOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(ConcurrentStackOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(DictionaryOfTKeyTValueConverter<,,>))] - [DynamicDependency("#ctor", typeof(ICollectionOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(IDictionaryOfTKeyTValueConverter<,,>))] - [DynamicDependency("#ctor", typeof(IEnumerableOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(IEnumerableWithAddMethodConverter<>))] - [DynamicDependency("#ctor", typeof(IListConverter<>))] - [DynamicDependency("#ctor", typeof(IListOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(ImmutableDictionaryOfTKeyTValueConverter<,,>))] - [DynamicDependency("#ctor", typeof(ImmutableEnumerableOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(IReadOnlyDictionaryOfTKeyTValueConverter<,,>))] - [DynamicDependency("#ctor", typeof(ISetOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(ListOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(QueueOfTConverter<,>))] - [DynamicDependency("#ctor", typeof(StackOfTConverter<,>))] public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { Type converterType; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs index b12f99f9aa0bb9..c00bed8f4ab807 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs @@ -3,40 +3,43 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Text.Json.Serialization { internal static class IEnumerableConverterFactoryHelpers { - private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray"; + // Immutable collection types. private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1"; - - private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList"; private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1"; private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1"; - - private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack"; private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1"; private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1"; - - private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue"; private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1"; private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1"; - - private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet"; private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1"; - - private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet"; private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1"; private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1"; - - private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary"; private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2"; private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2"; + private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2"; + // Immutable collection builder types. + private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray"; + private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList"; + private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack"; + private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue"; + private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet"; + private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet"; + private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary"; private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary"; - private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2"; + + private const string CreateRangeMethodName = "CreateRange"; + private const string CreateRangeMethodNameForEnumerable = "CreateRange`1"; + private const string CreateRangeMethodNameForDictionary = "CreateRange`2"; + + private const string ImmutableCollectionsAssembly = "System.Collections.Immutable"; internal static Type? GetCompatibleGenericBaseClass(this Type type, Type baseType) { @@ -139,19 +142,27 @@ public static bool IsImmutableEnumerableType(this Type type) } } + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableArrayTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableListTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableStackTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableQueueTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableSortedSetTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForEnumerable, ImmutableHashSetTypeName, ImmutableCollectionsAssembly)] public static MethodInfo GetImmutableEnumerableCreateRangeMethod(this Type type, Type elementType) { - Type constructingType = GetImmutableEnumerableConstructingType(type); - - MethodInfo[] constructingTypeMethods = constructingType.GetMethods(); - foreach (MethodInfo method in constructingTypeMethods) + Type? constructingType = GetImmutableEnumerableConstructingType(type); + if (constructingType != null) { - if (method.Name == "CreateRange" - && method.GetParameters().Length == 1 - && method.IsGenericMethod - && method.GetGenericArguments().Length == 1) + MethodInfo[] constructingTypeMethods = constructingType.GetMethods(); + foreach (MethodInfo method in constructingTypeMethods) { - return method.MakeGenericMethod(elementType); + if (method.Name == CreateRangeMethodName && + method.GetParameters().Length == 1 && + method.IsGenericMethod && + method.GetGenericArguments().Length == 1) + { + return method.MakeGenericMethod(elementType); + } } } @@ -159,19 +170,23 @@ public static MethodInfo GetImmutableEnumerableCreateRangeMethod(this Type type, return null!; } + [DynamicDependency(CreateRangeMethodNameForDictionary, ImmutableDictionaryTypeName, ImmutableCollectionsAssembly)] + [DynamicDependency(CreateRangeMethodNameForDictionary, ImmutableSortedDictionaryTypeName, ImmutableCollectionsAssembly)] public static MethodInfo GetImmutableDictionaryCreateRangeMethod(this Type type, Type elementType) { - Type constructingType = GetImmutableDictionaryConstructingType(type); - - MethodInfo[] constructingTypeMethods = constructingType.GetMethods(); - foreach (MethodInfo method in constructingTypeMethods) + Type? constructingType = GetImmutableDictionaryConstructingType(type); + if (constructingType != null) { - if (method.Name == "CreateRange" - && method.GetParameters().Length == 1 - && method.IsGenericMethod - && method.GetGenericArguments().Length == 2) + MethodInfo[] constructingTypeMethods = constructingType.GetMethods(); + foreach (MethodInfo method in constructingTypeMethods) { - return method.MakeGenericMethod(typeof(string), elementType); + if (method.Name == CreateRangeMethodName && + method.GetParameters().Length == 1 && + method.IsGenericMethod && + method.GetGenericArguments().Length == 2) + { + return method.MakeGenericMethod(typeof(string), elementType); + } } } @@ -179,7 +194,7 @@ public static MethodInfo GetImmutableDictionaryCreateRangeMethod(this Type type, return null!; } - private static Type GetImmutableEnumerableConstructingType(Type type) + private static Type? GetImmutableEnumerableConstructingType(Type type) { Debug.Assert(type.IsImmutableEnumerableType()); @@ -216,14 +231,13 @@ private static Type GetImmutableEnumerableConstructingType(Type type) default: // We verified that the type is an immutable collection, so the // generic definition is one of the above. - return null!; + return null; } - // This won't be null because we verified the assembly is actually System.Collections.Immutable. - return underlyingType.Assembly.GetType(constructingTypeName)!; + return underlyingType.Assembly.GetType(constructingTypeName); } - private static Type GetImmutableDictionaryConstructingType(Type type) + private static Type? GetImmutableDictionaryConstructingType(Type type) { Debug.Assert(type.IsImmutableDictionaryType()); @@ -245,11 +259,10 @@ private static Type GetImmutableDictionaryConstructingType(Type type) default: // We verified that the type is an immutable collection, so the // generic definition is one of the above. - return null!; + return null; } - // This won't be null because we verified the assembly is actually System.Collections.Immutable. - return underlyingType.Assembly.GetType(constructingTypeName)!; + return underlyingType.Assembly.GetType(constructingTypeName); } public static bool IsNonGenericStackOrQueue(this Type type) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs index 3a9db46fa8d929..ca1dda48f2dade 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs @@ -5,7 +5,6 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Text.Json.Serialization.Converters @@ -23,10 +22,6 @@ public override bool CanConvert(Type typeToConvert) return true; } - [DynamicDependency("#ctor", typeof(KeyValuePairConverter<,>))] - [DynamicDependency("#ctor", typeof(LargeObjectWithParameterizedConstructorConverter<>))] - [DynamicDependency("#ctor", typeof(ObjectDefaultConverter<>))] - [DynamicDependency("#ctor", typeof(SmallObjectWithParameterizedConstructorConverter<,,,,>))] public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { if (IsKeyValuePair(typeToConvert)) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs index 49abb0e2cb6d04..90835d5bd3086e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Reflection; -using System.Diagnostics.CodeAnalysis; namespace System.Text.Json.Serialization.Converters { @@ -18,9 +17,6 @@ public override bool CanConvert(Type type) return type.IsEnum; } - [DynamicDependency( - "#ctor(System.Text.Json.Serialization.Converters.EnumConverterOptions,System.Text.Json.JsonSerializerOptions)", - typeof(EnumConverter<>))] public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) { JsonConverter converter = (JsonConverter)Activator.CreateInstance( diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs index bfdbd5993c65b4..821a999639c118 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Helpers.cs @@ -10,6 +10,9 @@ namespace System.Text.Json { public static partial class JsonSerializer { + // Members accessed by the serializer when deserializing. + private const DynamicallyAccessedMemberTypes MembersAccessedOnRead = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties; + [return: MaybeNull] private static TValue ReadCore(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs index 3aacdc8839b403..b840279540cc84 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Span.cs @@ -24,7 +24,7 @@ public static partial class JsonSerializer /// for or its serializable members. /// [return: MaybeNull] - public static TValue Deserialize(ReadOnlySpan utf8Json, JsonSerializerOptions? options = null) + public static TValue Deserialize<[DynamicallyAccessedMembers(MembersAccessedOnRead)] TValue>(ReadOnlySpan utf8Json, JsonSerializerOptions? options = null) { if (options == null) { @@ -56,7 +56,7 @@ public static TValue Deserialize(ReadOnlySpan utf8Json, JsonSerial /// There is no compatible /// for or its serializable members. /// - public static object? Deserialize(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize(ReadOnlySpan utf8Json, [DynamicallyAccessedMembers(MembersAccessedOnRead)] Type returnType, JsonSerializerOptions? options = null) { if (returnType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs index 4bd48ea447bb09..35a607ed8b79a9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Stream.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.Json.Serialization; using System.Threading; @@ -35,7 +36,7 @@ public static partial class JsonSerializer /// There is no compatible /// for or its serializable members. /// - public static ValueTask DeserializeAsync( + public static ValueTask DeserializeAsync<[DynamicallyAccessedMembers(MembersAccessedOnRead)] TValue>( Stream utf8Json, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) @@ -73,7 +74,7 @@ public static ValueTask DeserializeAsync( /// public static ValueTask DeserializeAsync( Stream utf8Json, - Type returnType, + [DynamicallyAccessedMembers(MembersAccessedOnRead)] Type returnType, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs index 082c49645379ea..adc5c2753a2285 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.String.cs @@ -36,7 +36,7 @@ public static partial class JsonSerializer /// UTF-8 methods since the implementation natively uses UTF-8. /// [return: MaybeNull] - public static TValue Deserialize(string json, JsonSerializerOptions? options = null) + public static TValue Deserialize<[DynamicallyAccessedMembers(MembersAccessedOnRead)] TValue>(string json, JsonSerializerOptions? options = null) { if (json == null) { @@ -68,7 +68,7 @@ public static TValue Deserialize(string json, JsonSerializerOptions? opt /// Using a is not as efficient as using the /// UTF-8 methods since the implementation natively uses UTF-8. /// - public static object? Deserialize(string json, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize(string json, [DynamicallyAccessedMembers(MembersAccessedOnRead)] Type returnType, JsonSerializerOptions? options = null) { if (json == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs index b6395bd5c9ee25..4cc19526b24990 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.Utf8JsonReader.cs @@ -54,7 +54,7 @@ public static partial class JsonSerializer /// /// [return: MaybeNull] - public static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions? options = null) + public static TValue Deserialize<[DynamicallyAccessedMembers(MembersAccessedOnRead)] TValue>(ref Utf8JsonReader reader, JsonSerializerOptions? options = null) { if (options == null) { @@ -112,7 +112,7 @@ public static TValue Deserialize(ref Utf8JsonReader reader, JsonSerializ /// Hence, , , are used while reading. /// /// - public static object? Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions? options = null) + public static object? Deserialize(ref Utf8JsonReader reader, [DynamicallyAccessedMembers(MembersAccessedOnRead)] Type returnType, JsonSerializerOptions? options = null) { if (returnType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs index cf948b2a694452..4cbdcfe76f7981 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.ByteArray.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics.CodeAnalysis; + namespace System.Text.Json { public static partial class JsonSerializer @@ -16,7 +18,9 @@ public static partial class JsonSerializer /// There is no compatible /// for or its serializable members. /// - public static byte[] SerializeToUtf8Bytes(TValue value, JsonSerializerOptions? options = null) + public static byte[] SerializeToUtf8Bytes<[DynamicallyAccessedMembers(MembersAccessedOnWrite)] TValue>( + TValue value, + JsonSerializerOptions? options = null) { return WriteCoreBytes(value, typeof(TValue), options); } @@ -38,7 +42,10 @@ public static byte[] SerializeToUtf8Bytes(TValue value, JsonSerializerOp /// There is no compatible /// for or its serializable members. /// - public static byte[] SerializeToUtf8Bytes(object? value, Type inputType, JsonSerializerOptions? options = null) + public static byte[] SerializeToUtf8Bytes( + object? value, + [DynamicallyAccessedMembers(MembersAccessedOnWrite)] Type inputType, + JsonSerializerOptions? options = null) { if (inputType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs index 1b8c7929e6cc18..27258abb972c6b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs @@ -3,12 +3,16 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; namespace System.Text.Json { public static partial class JsonSerializer { + // Members accessed by the serializer when serializing. + private const DynamicallyAccessedMemberTypes MembersAccessedOnWrite = DynamicallyAccessedMemberTypes.PublicProperties; + private static void WriteCore( Utf8JsonWriter writer, in TValue value, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs index 07856fed8faf62..8b9bf61c3d13f0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text.Json.Serialization; using System.Threading; @@ -26,7 +27,7 @@ public static partial class JsonSerializer /// There is no compatible /// for or its serializable members. /// - public static Task SerializeAsync( + public static Task SerializeAsync<[DynamicallyAccessedMembers(MembersAccessedOnWrite)] TValue>( Stream utf8Json, TValue value, JsonSerializerOptions? options = null, @@ -60,7 +61,7 @@ public static Task SerializeAsync( public static Task SerializeAsync( Stream utf8Json, object? value, - Type inputType, + [DynamicallyAccessedMembers(MembersAccessedOnWrite)] Type inputType, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs index b09b1e68e618b9..a20e732f51ed6c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.String.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics.CodeAnalysis; + namespace System.Text.Json { public static partial class JsonSerializer @@ -20,7 +22,7 @@ public static partial class JsonSerializer /// encoding since the implementation internally uses UTF-8. See also /// and . /// - public static string Serialize(TValue value, JsonSerializerOptions? options = null) + public static string Serialize<[DynamicallyAccessedMembers(MembersAccessedOnWrite)] TValue>(TValue value, JsonSerializerOptions? options = null) { return Serialize(value, typeof(TValue), options); } @@ -43,7 +45,10 @@ public static string Serialize(TValue value, JsonSerializerOptions? opti /// encoding since the implementation internally uses UTF-8. See also /// and . /// - public static string Serialize(object? value, Type inputType, JsonSerializerOptions? options = null) + public static string Serialize( + object? value, + [DynamicallyAccessedMembers(MembersAccessedOnWrite)] Type inputType, + JsonSerializerOptions? options = null) { if (inputType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs index c9a5c31dea02bc..729bbc2bff269b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Utf8JsonWriter.cs @@ -2,8 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Text.Json.Serialization; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; namespace System.Text.Json { @@ -22,7 +23,10 @@ public static partial class JsonSerializer /// There is no compatible /// for or its serializable members. /// - public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSerializerOptions? options = null) + public static void Serialize<[DynamicallyAccessedMembers(MembersAccessedOnWrite)] TValue>( + Utf8JsonWriter writer, + TValue value, + JsonSerializerOptions? options = null) { Serialize(writer, value, typeof(TValue), options); } @@ -44,7 +48,11 @@ public static void Serialize(Utf8JsonWriter writer, TValue value, JsonSe /// There is no compatible /// for or its serializable members. /// - public static void Serialize(Utf8JsonWriter writer, object? value, Type inputType, JsonSerializerOptions? options = null) + public static void Serialize( + Utf8JsonWriter writer, + object? value, + [DynamicallyAccessedMembers(MembersAccessedOnWrite)] Type inputType, + JsonSerializerOptions? options = null) { if (inputType == null) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs index fa9e10bfd7a65b..55e59178270755 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json.Serialization.Converters; @@ -54,9 +53,6 @@ public override bool CanConvert(Type typeToConvert) } /// - [DynamicDependency( - "#ctor(System.Text.Json.Serialization.Converters.EnumConverterOptions,System.Text.Json.JsonNamingPolicy,System.Text.Json.JsonSerializerOptions)", - typeof(EnumConverter<>))] public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { JsonConverter converter = (JsonConverter)Activator.CreateInstance( diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Array.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Array.cs new file mode 100644 index 00000000000000..6ba4950d4cf855 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Array.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Array is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(int[])); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentDictionary.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentDictionary.cs new file mode 100644 index 00000000000000..23f433f4dbb7d9 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentDictionary.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Concurrent; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ConcurrentDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(ConcurrentDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentQueue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentQueue.cs new file mode 100644 index 00000000000000..ff624deea7cabd --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentQueue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Concurrent; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ConcurrentQueue is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ConcurrentQueue)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentStack.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentStack.cs new file mode 100644 index 00000000000000..2c0b396405f323 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ConcurrentStack.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Concurrent; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ConcurrentStack is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ConcurrentStack)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/DictionaryOfTKeyTValue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/DictionaryOfTKeyTValue.cs new file mode 100644 index 00000000000000..b98e2c8d51e328 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/DictionaryOfTKeyTValue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Dictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(Dictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/HashSetOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/HashSetOfT.cs new file mode 100644 index 00000000000000..45c468c6b69211 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/HashSetOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing HashSet is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(HashSet)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Hashtable.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Hashtable.cs new file mode 100644 index 00000000000000..684837f1dbbb4e --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Hashtable.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Hashtable is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(Hashtable)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollection.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollection.cs new file mode 100644 index 00000000000000..aacd989306d333 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollection.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ICollection is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ICollection>)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollectionOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollectionOfT.cs new file mode 100644 index 00000000000000..3ede4f68397425 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ICollectionOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ICollection is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ICollection)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionary.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionary.cs new file mode 100644 index 00000000000000..5f4da2a9f940a3 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionary.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(IDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionaryOfTKeyTValue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionaryOfTKeyTValue.cs new file mode 100644 index 00000000000000..0f107fbe515c2d --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IDictionaryOfTKeyTValue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(IDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerable.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerable.cs new file mode 100644 index 00000000000000..e6af50148e98f0 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerable.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IEnumerable is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IEnumerable)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerableOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerableOfT.cs new file mode 100644 index 00000000000000..83cc0a9d811ebe --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IEnumerableOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IEnumerable is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IEnumerable)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableDictionary.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableDictionary.cs new file mode 100644 index 00000000000000..259f9ce3e76b50 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableDictionary.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IImmutableDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(IImmutableDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableList.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableList.cs new file mode 100644 index 00000000000000..29f05c4b54ca8b --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableList.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IImmutableList is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IImmutableList)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableQueue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableQueue.cs new file mode 100644 index 00000000000000..c8b6d7681c44a7 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableQueue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IImmutableQueue is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IImmutableQueue)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableSet.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableSet.cs new file mode 100644 index 00000000000000..668ee52cd99fae --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableSet.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IImmutableSet is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IImmutableSet)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableStack.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableStack.cs new file mode 100644 index 00000000000000..d91ddbf5a1df00 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IImmutableStack.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IImmutableStack is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IImmutableStack)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IList.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IList.cs new file mode 100644 index 00000000000000..ea29d188bdf750 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IList.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IList is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IList)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IListOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IListOfT.cs new file mode 100644 index 00000000000000..870a26a09efac0 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IListOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IList is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(IList)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IReadOnlyDictionaryOfTKeyTValue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IReadOnlyDictionaryOfTKeyTValue.cs new file mode 100644 index 00000000000000..b2c49a70b85e2d --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/IReadOnlyDictionaryOfTKeyTValue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing IReadOnlyDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(IReadOnlyDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ISetOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ISetOfT.cs new file mode 100644 index 00000000000000..74c715c39c1d11 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ISetOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ISet is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ISet)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableArray.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableArray.cs new file mode 100644 index 00000000000000..fbf9c020f2daff --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableArray.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableArray is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableArray)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableDictionary.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableDictionary.cs new file mode 100644 index 00000000000000..cdd919095b4734 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableDictionary.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableHashSet.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableHashSet.cs new file mode 100644 index 00000000000000..59d0a43cd3e57d --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableHashSet.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableHashSet is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableHashSet)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableList.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableList.cs new file mode 100644 index 00000000000000..9f784804c8fa89 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableList.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableList is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableList)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableQueue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableQueue.cs new file mode 100644 index 00000000000000..ffbd5a9371c143 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableQueue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableQueue is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableQueue)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedDictionary.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedDictionary.cs new file mode 100644 index 00000000000000..4c06d425bb1489 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedDictionary.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableSortedDictionary is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""Key"":1}"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableSortedDictionary)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedSet.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedSet.cs new file mode 100644 index 00000000000000..c19f2425a80d5c --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableSortedSet.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableSortedSet is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableSortedSet)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableStack.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableStack.cs new file mode 100644 index 00000000000000..1642fc4db0a542 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ImmutableStack.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing ImmutableStack is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(ImmutableStack)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ListOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ListOfT.cs new file mode 100644 index 00000000000000..b038d827296acd --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/ListOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing List is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(List)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Queue.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Queue.cs new file mode 100644 index 00000000000000..aba39cd93dd239 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Queue.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Queue is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(Queue)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/QueueOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/QueueOfT.cs new file mode 100644 index 00000000000000..c2b90b17f3e805 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/QueueOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Queue is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(Queue)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Stack.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Stack.cs new file mode 100644 index 00000000000000..abf0cfbfabf61b --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/Stack.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Stack is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(Stack)); + if (!(TestHelper.AssertCollectionAndSerialize(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/StackOfT.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/StackOfT.cs new file mode 100644 index 00000000000000..dd08c4be8f07a6 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Collections/StackOfT.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's warm up routine for (de)serializing Stack is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + object obj = JsonSerializer.Deserialize(json, typeof(Stack)); + if (!(TestHelper.AssertCollectionAndSerialize>(obj, json))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/EnumConverterTest.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/EnumConverterTest.cs new file mode 100644 index 00000000000000..ec7d6687a434ed --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/EnumConverterTest.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the enum converter factory is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = JsonSerializer.Serialize(new ClassWithDay()); + return json == @"{""Day"":0}" ? 100 : -1; + } + } + + internal class ClassWithDay + { + public DayOfWeek Day { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/Helper.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/Helper.cs new file mode 100644 index 00000000000000..470f244e496c64 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/Helper.cs @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace SerializerTrimmingTest +{ + internal static class TestHelper + { + /// + /// Used when comparing JSON payloads with more than two properties. + /// We cannot check for string equality since property ordering depends + /// on reflection ordering which is not guaranteed. + /// + public static bool JsonEqual(string expected, string actual) + { + using JsonDocument expectedDom = JsonDocument.Parse(expected); + using JsonDocument actualDom = JsonDocument.Parse(actual); + return JsonEqual(expectedDom.RootElement, actualDom.RootElement); + } + + private static bool JsonEqual(JsonElement expected, JsonElement actual) + { + JsonValueKind valueKind = expected.ValueKind; + if (valueKind != actual.ValueKind) + { + return false; + } + + switch (valueKind) + { + case JsonValueKind.Object: + var propertyNames = new HashSet(); + + foreach (JsonProperty property in expected.EnumerateObject()) + { + propertyNames.Add(property.Name); + } + + foreach (JsonProperty property in actual.EnumerateObject()) + { + propertyNames.Add(property.Name); + } + + foreach (string name in propertyNames) + { + if (!JsonEqual(expected.GetProperty(name), actual.GetProperty(name))) + { + return false; + } + } + + return true; + case JsonValueKind.Array: + JsonElement.ArrayEnumerator expectedEnumerator = actual.EnumerateArray(); + JsonElement.ArrayEnumerator actualEnumerator = expected.EnumerateArray(); + + while (expectedEnumerator.MoveNext()) + { + if (!actualEnumerator.MoveNext()) + { + return false; + } + + if (!JsonEqual(expectedEnumerator.Current, actualEnumerator.Current)) + { + return false; + } + } + + return !actualEnumerator.MoveNext(); + case JsonValueKind.String: + return expected.GetString() == actual.GetString(); + case JsonValueKind.Number: + case JsonValueKind.True: + case JsonValueKind.False: + case JsonValueKind.Null: + return expected.GetRawText() == actual.GetRawText(); + default: + throw new NotSupportedException($"Unexpected JsonValueKind: JsonValueKind.{valueKind}."); + } + } + + public static bool AssertCollectionAndSerialize(object obj, string json) + { + return obj is T && JsonSerializer.Serialize(obj) == json; + } + } + + internal class MyClass + { + public int X { get; set; } + public int Y { get; set; } + } + + internal struct MyStruct + { + public int X { get; } + public int Y { get; } + + [JsonConstructor] + public MyStruct(int x, int y) => (X, Y) = (x, y); + } + + internal class MyClassWithParameterizedCtor + { + public int X { get; set; } + public int Y { get; set; } + + public MyClassWithParameterizedCtor(int x, int y) => (X, Y) = (x, y); + } + + internal class MyBigClass + { + public string A { get; } + public string B { get; } + public string C { get; } + public int One { get; } + public int Two { get; } + public int Three { get; } + + public MyBigClass(string a, string b, string c, int one, int two, int three) + { + A = a; + B = b; + C = c; + One = one; + Two = two; + Three = three; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/JsonConverterAttributeTest.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/JsonConverterAttributeTest.cs new file mode 100644 index 00000000000000..50ee0948be7738 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/JsonConverterAttributeTest.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the public parameterless ctor of the ConverterType property on + /// JsonConstructorAttribute is preserved when needed in a trimmed application. + /// + internal class Program + { + static int Main(string[] args) + { + string json = JsonSerializer.Serialize(new ClassWithDay()); + return json == @"{""Day"":""Sunday""}" ? 100 : -1; + } + } + + internal class ClassWithDay + { + [JsonConverterAttribute(typeof(JsonStringEnumConverter))] + public DayOfWeek Day { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/ObjectConvertersTest.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/ObjectConvertersTest.cs new file mode 100644 index 00000000000000..c77db580954cbf --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/ObjectConvertersTest.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the object converter factory is linker-safe. + /// + internal class Program + { + static int Main(string[] args) + { + string json = @"{""X"":1,""Y"":2}"; + + MyClass @class = JsonSerializer.Deserialize(json); // ObjectDefaultConverter + if (!TestHelper.JsonEqual(json, JsonSerializer.Serialize(@class))) + { + return -1; + } + + MyStruct @struct = JsonSerializer.Deserialize(json); // SmallObjectWithParameterizedConstructorConverter + if (!TestHelper.JsonEqual(json, JsonSerializer.Serialize(@struct))) + { + return -1; + } + + json = @"{""A"":""A"",""B"":""B"",""C"":""C"",""One"":1,""Two"":2,""Three"":3}"; + MyBigClass bigClass = JsonSerializer.Deserialize(json); // LargeObjectWithParameterizedConstructorConverter + if (!TestHelper.JsonEqual(json, JsonSerializer.Serialize(bigClass))) + { + return -1; + } + + json = @"{""Key"":1,""Value"":2}"; + KeyValuePair kvp = JsonSerializer.Deserialize>(json); // KeyValuePairConverter + if (!TestHelper.JsonEqual(json, JsonSerializer.Serialize(kvp))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.BoxedObject.cs new file mode 100644 index 00000000000000..4f435e60da05ce --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.BoxedObject.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + int[] arr = (int[])JsonSerializer.Deserialize(ref reader, typeof(int[])); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + var obj = (MyClassWithParameterizedCtor)JsonSerializer.Deserialize(json, typeof(MyClassWithParameterizedCtor)); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.TypedObject.cs new file mode 100644 index 00000000000000..5b4c08ea88757a --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromReader.TypedObject.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + Utf8JsonReader reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + int[] arr = JsonSerializer.Deserialize(ref reader); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + MyClassWithParameterizedCtor obj = JsonSerializer.Deserialize(ref reader); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.BoxedObject.cs new file mode 100644 index 00000000000000..2c849e49703aa5 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.BoxedObject.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(ReadOnlySpan utf8Json, Type returnType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + int[] arr = (int[])JsonSerializer.Deserialize(Encoding.UTF8.GetBytes(json), typeof(int[])); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + var obj = (MyClassWithParameterizedCtor)JsonSerializer.Deserialize(Encoding.UTF8.GetBytes(json), typeof(MyClassWithParameterizedCtor)); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.TypedObject.cs new file mode 100644 index 00000000000000..cf2ec8bd0f64f5 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromSpan.TypedObject.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(ReadOnlySpan utf8Json, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + int[] arr = JsonSerializer.Deserialize(Encoding.UTF8.GetBytes(json)); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + MyClassWithParameterizedCtor obj = JsonSerializer.Deserialize(Encoding.UTF8.GetBytes(json)); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.BoxedObject.cs new file mode 100644 index 00000000000000..6223ca80dc7438 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.BoxedObject.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(string json, Type returnType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + int[] arr = (int[])JsonSerializer.Deserialize(json, typeof(int[])); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + var obj = (MyClassWithParameterizedCtor)JsonSerializer.Deserialize(json, typeof(MyClassWithParameterizedCtor)); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.TypedObject.cs new file mode 100644 index 00000000000000..997959d006945a --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Deserialize.FromString.TypedObject.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(string json, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + string json = "[1]"; + int[] arr = JsonSerializer.Deserialize(json); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + + json = @"{""X"":1,""Y"":2}"; + MyClassWithParameterizedCtor obj = JsonSerializer.Deserialize(json); + if (obj == null) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.BoxedObject.cs new file mode 100644 index 00000000000000..07825653353c7e --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.BoxedObject.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.DeserializeAsync(Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors properties and public are expected to be preserved. + /// + internal class Program + { + static async Task Main(string[] args) + { + string json = "[1]"; + + using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) + { + int[] arr = (int[])(await JsonSerializer.DeserializeAsync(stream, typeof(int[]))); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + } + + json = @"{""X"":1,""Y"":2}"; + + using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) + { + var obj = (MyClassWithParameterizedCtor)(await JsonSerializer.DeserializeAsync(stream, typeof(MyClassWithParameterizedCtor))); + if (obj == null) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.TypedObject.cs new file mode 100644 index 00000000000000..7222ffb2600f91 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/DeserializeAsync.FromStream.TypedObject.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.DeserializeAsync(Stream utf8Json, JsonSerializerOptions options, CancellationToken cancellationToken) + /// overload has the appropriate linker annotations. + /// A collection and a POCO are used. Public constructors and public properties are expected to be preserved. + /// + internal class Program + { + static async Task Main(string[] args) + { + string json = "[1]"; + using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) + { + int[] arr = (int[])(await JsonSerializer.DeserializeAsync(stream)); + if (arr == null || arr.Length != 1 || arr[0] != 1) + { + return -1; + } + } + + json = @"{""X"":1,""Y"":2}"; + using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) + { + var obj = (MyClassWithParameterizedCtor)(await JsonSerializer.DeserializeAsync(stream)); + if (obj == null) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.BoxedObject.cs new file mode 100644 index 00000000000000..18de37d307f1b1 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.BoxedObject.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.SerializeToUtf8Bytes(object value, Type inputType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + int[] arr = new [] { 1 }; + string expected = "[1]"; + string actual = Encoding.UTF8.GetString(JsonSerializer.SerializeToUtf8Bytes(arr, typeof(int[]))); + if (actual != expected) + { + return -1; + } + + MyStruct obj = default; + expected = @"{""X"":0,""Y"":0}"; + actual = Encoding.UTF8.GetString(JsonSerializer.SerializeToUtf8Bytes(obj, typeof(MyStruct))); + if (!TestHelper.JsonEqual(expected, actual)) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.TypedObject.cs new file mode 100644 index 00000000000000..8ccf6cde59ea98 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToByteArray.TypedObject.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.SerializeToUtf8Bytes(T value, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + int[] arr = new [] { 1 }; + string expected = "[1]"; + string actual = Encoding.UTF8.GetString(JsonSerializer.SerializeToUtf8Bytes(arr)); + if (actual != expected) + { + return -1; + } + + MyStruct obj = default; + expected = @"{""X"":0,""Y"":0}"; + actual = Encoding.UTF8.GetString(JsonSerializer.SerializeToUtf8Bytes(obj)); + if (!TestHelper.JsonEqual(expected, actual)) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.WithWriter.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.WithWriter.cs new file mode 100644 index 00000000000000..70b9a360e74bd1 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.WithWriter.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Serialize(Utf8JsonWriter writer, object value, Type inputType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + { + int[] arr = new [] { 1 }; + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + JsonSerializer.Serialize(writer, arr, typeof(int[])); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (actual != "[1]") + { + return -1; + } + } + + { + MyStruct obj = default; + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + JsonSerializer.Serialize(writer, obj, typeof(MyStruct)); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", actual)) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.cs new file mode 100644 index 00000000000000..242cc7c4aa7894 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.BoxedObject.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests the serializer's JsonSerializer.Serialize(object value, Type inputType, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + int[] arr = new [] { 1 }; + if (JsonSerializer.Serialize(arr, typeof(int[])) != "[1]") + { + return -1; + } + + MyStruct obj = default; + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", JsonSerializer.Serialize(obj, typeof(MyStruct)))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.WithWriter.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.WithWriter.cs new file mode 100644 index 00000000000000..b0e0bb75db47b7 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.WithWriter.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Serialize(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + { + int[] arr = new [] { 1 }; + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + JsonSerializer.Serialize(writer, arr); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (actual != "[1]") + { + return -1; + } + } + + { + MyStruct obj = default; + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + JsonSerializer.Serialize(writer, obj); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", actual)) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.cs new file mode 100644 index 00000000000000..5365c89818491d --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/Serialize.ToString.TypedObject.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Text.Json; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.Deserialize(ref Utf8JsonReader reader, JsonSerializerOptions options) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static int Main(string[] args) + { + int[] arr = new [] { 1 }; + if (JsonSerializer.Serialize(arr) != "[1]") + { + return -1; + } + + MyStruct obj = default; + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", JsonSerializer.Serialize(obj))) + { + return -1; + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.BoxedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.BoxedObject.cs new file mode 100644 index 00000000000000..e5069c29f52607 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.BoxedObject.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.SerializeAsync(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static async Task Main(string[] args) + { + using (var stream = new MemoryStream()) + { + int[] arr = new [] { 1 }; + await JsonSerializer.SerializeAsync(stream, arr, typeof(int[])); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if ("[1]" != actual) + { + return -1; + } + } + + using (var stream = new MemoryStream()) + { + MyStruct obj = default; + await JsonSerializer.SerializeAsync(stream, obj, typeof(MyStruct)); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", actual)) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.TypedObject.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.TypedObject.cs new file mode 100644 index 00000000000000..37e4b36f3fc258 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/SerializerEntryPoint/SerializeAsync.ToStream.TypedObject.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace SerializerTrimmingTest +{ + /// + /// Tests that the serializer's JsonSerializer.SerializeAsync(Stream utf8Json, T value, JsonSerializerOptions options, CancellationToken cancellationToken) + /// overload has the appropriate linker annotations. A collection and a POCO are used. Public properties are expected to be preserved. + /// + internal class Program + { + static async Task Main(string[] args) + { + using (var stream = new MemoryStream()) + { + int[] arr = new [] { 1 }; + await JsonSerializer.SerializeAsync(stream, arr); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (actual != "[1]") + { + return -1; + } + } + + using (var stream = new MemoryStream()) + { + MyStruct obj = default; + await JsonSerializer.SerializeAsync(stream, obj); + string actual = Encoding.UTF8.GetString(stream.ToArray()); + if (!TestHelper.JsonEqual(@"{""X"":0,""Y"":0}", actual)) + { + return -1; + } + } + + return 100; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/StackOrQueueNotRootedTest.cs b/src/libraries/System.Text.Json/tests/TrimmingTests/StackOrQueueNotRootedTest.cs index e94dd33583e6c7..262330a4bfe91d 100644 --- a/src/libraries/System.Text.Json/tests/TrimmingTests/StackOrQueueNotRootedTest.cs +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/StackOrQueueNotRootedTest.cs @@ -40,4 +40,3 @@ static int Main(string[] args) private static Type GetTypeIfExists(string name) => Type.GetType(name, false); } - diff --git a/src/libraries/System.Text.Json/tests/TrimmingTests/System.Text.Json.TrimmingTests.proj b/src/libraries/System.Text.Json/tests/TrimmingTests/System.Text.Json.TrimmingTests.proj index da4a46f2ae141a..ae1307bd108f26 100644 --- a/src/libraries/System.Text.Json/tests/TrimmingTests/System.Text.Json.TrimmingTests.proj +++ b/src/libraries/System.Text.Json/tests/TrimmingTests/System.Text.Json.TrimmingTests.proj @@ -1,5 +1,158 @@ + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + Helper.cs + + + + + Helper.cs + + + +