diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index ae38bf43c3b497..bbdd17bddb8c22 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -196,7 +196,7 @@ public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGene _stringType = _metadataLoadContext.Resolve(SpecialType.System_String); _dateTimeOffsetType = _metadataLoadContext.Resolve(typeof(DateTimeOffset)); - _byteArrayType = _metadataLoadContext.Resolve(typeof(byte[])); + _byteArrayType = _metadataLoadContext.Resolve(typeof(byte)).MakeArrayType(); _guidType = _metadataLoadContext.Resolve(typeof(Guid)); _uriType = _metadataLoadContext.Resolve(typeof(Uri)); _versionType = _metadataLoadContext.Resolve(typeof(Version)); diff --git a/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs b/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs index 15020ec6ea6217..e04adf3c21c308 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -20,7 +21,13 @@ public MetadataLoadContextInternal(Compilation compilation) _compilation = compilation; } - public Type? Resolve(Type type) => Resolve(type.FullName!); + public Compilation Compilation => _compilation; + + public Type? Resolve(Type type) + { + Debug.Assert(!type.IsArray, "Resolution logic only capable of handling named types."); + return Resolve(type.FullName!); + } public Type? Resolve(string fullyQualifiedMetadataName) { diff --git a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs index 71ea983e90ab13..5d4d778bc6348d 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs @@ -281,6 +281,11 @@ public override Type GetElementType() return _elementType; } + public override Type MakeArrayType() + { + return _metadataLoadContext.Compilation.CreateArrayTypeSymbol(_typeSymbol).AsType(_metadataLoadContext); + } + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs index ef79671ba640ea..24559eb6c86a54 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs @@ -31,6 +31,7 @@ public interface ITestContext public JsonTypeInfo MyNestedClass { get; } public JsonTypeInfo MyNestedNestedClass { get; } public JsonTypeInfo ObjectArray { get; } + public JsonTypeInfo ByteArray { get; } public JsonTypeInfo String { get; } public JsonTypeInfo<(string Label1, int Label2, bool)> ValueTupleStringInt32Boolean { get; } public JsonTypeInfo ClassWithEnumAndNullable { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs index 7e83f1ae37feaa..81513b46499a70 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs @@ -22,6 +22,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(MyTypeWithPropertyOrdering))] [JsonSerializable(typeof(MyIntermediateType))] [JsonSerializable(typeof(HighLowTempsImmutable))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs index a9932ede2bf80b..f83a2fc923421b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs @@ -24,6 +24,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -66,6 +67,7 @@ public override void EnsureFastPathGeneratedAsExpected() Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler); Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler); Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ByteArray.SerializeHandler); Assert.Null(MetadataWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler); Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.SerializeHandler); Assert.Null(MetadataWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); @@ -103,6 +105,7 @@ public override void EnsureFastPathGeneratedAsExpected() [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof((string Label1, int Label2, bool)))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] @@ -168,6 +171,7 @@ public override void EnsureFastPathGeneratedAsExpected() Assert.Null(MetadataContext.Default.MyNestedClass.SerializeHandler); Assert.Null(MetadataContext.Default.MyNestedNestedClass.SerializeHandler); Assert.Null(MetadataContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MetadataContext.Default.ByteArray.SerializeHandler); Assert.Null(MetadataContext.Default.SampleEnum.SerializeHandler); Assert.Null(MetadataContext.Default.String.SerializeHandler); Assert.Null(MetadataContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs index 0cb5cf13d5e9b3..060db030bcadab 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs @@ -25,6 +25,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] @@ -68,6 +69,7 @@ public override void EnsureFastPathGeneratedAsExpected() Assert.NotNull(MixedModeContext.Default.MyNestedClass.SerializeHandler); Assert.NotNull(MixedModeContext.Default.MyNestedNestedClass.SerializeHandler); Assert.Null(MixedModeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MixedModeContext.Default.ByteArray.SerializeHandler); Assert.Null(MixedModeContext.Default.SampleEnum.SerializeHandler); Assert.Null(MixedModeContext.Default.String.SerializeHandler); Assert.NotNull(MixedModeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs index 8348e7c0df8e4e..ee891562fffee7 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs @@ -639,6 +639,19 @@ public virtual void SerializeObjectArray_SimpleTypes_WithCustomOptions() Assert.Equal("\"World\"", world.GetRawText()); } + [Fact] + public virtual void SerializeByteArray() + { + byte[] value = new byte[] { 1, 2, 3 }; + const string expectedJson = "\"AQID\""; + + string actualJson = JsonSerializer.Serialize(value, DefaultContext.ByteArray); + Assert.Equal(expectedJson, actualJson); + + byte[] arr = JsonSerializer.Deserialize(actualJson, DefaultContext.ByteArray); + Assert.Equal(value, arr); + } + [Fact] public virtual void HandlesNestedTypes() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs index 0c9079a259e39c..57f663e8b36339 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs @@ -25,6 +25,7 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof((string Label1, int Label2, bool)))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] @@ -62,6 +63,7 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -100,6 +102,7 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -149,6 +152,7 @@ public override void EnsureFastPathGeneratedAsExpected() Assert.NotNull(SerializationContext.Default.MyNestedClass.SerializeHandler); Assert.NotNull(SerializationContext.Default.MyNestedNestedClass.SerializeHandler); Assert.Null(SerializationContext.Default.ObjectArray.SerializeHandler); + Assert.Null(SerializationContext.Default.ByteArray.SerializeHandler); Assert.Null(SerializationContext.Default.String.SerializeHandler); Assert.NotNull(SerializationContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); Assert.NotNull(SerializationContext.Default.ClassWithEnumAndNullable.SerializeHandler); @@ -451,6 +455,7 @@ public override void EnsureFastPathGeneratedAsExpected() Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler); Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler); Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ByteArray.SerializeHandler); Assert.Null(SerializationWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler); Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.SerializeHandler); Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);