Skip to content

Serialization of ReadOnlyMemory<byte> with [JsonIgnore] attribute in .NET 6 and .NET 7 RC1 #76807

Description

@MartyIX

Description

JsonSerializer.Serialize(..) method works differently in .NET 6 and in .NET 7 for ReadOnlyMemory<byte> property with [JsonIgnore] attribute.

Reproduction Steps

The issue can be reproduced using the following two files

JsonSerializerRepro.csproj:

<ProjectSdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<!-- Works with .NET 6 -->
<TargetFramework>net6.0</TargetFramework>
<!-- Fails with .NET 7 --><!--<TargetFramework>net7.0</TargetFramework>-->
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

Program.cs:

usingSystem;usingSystem.Text.Json;usingSystem.Text.Json.Serialization;namespaceJsonSerializeRepro;publicstaticclassProgram{publicstaticvoidMain(string[]args){ReadOnlyMemory<byte>binaryData=Array.Empty<byte>();InstallScriptRequestinstallScriptRequest=new(binaryData,upgrade:true);stringjson=JsonSerializer.Serialize(installScriptRequest);Console.WriteLine(json);}}publicclassInstallScriptRequest{[JsonIgnore]publicintBinaryDataMaxSize=>1024*1024;[JsonIgnore]publicReadOnlyMemory<byte>BinaryData{get;set;}publicboolUpgrade{get;}publicInstallScriptRequest(ReadOnlyMemory<byte>binaryData,boolupgrade){this.BinaryData=binaryData;this.Upgrade=upgrade;}}

Expected behavior

When run as .NET 6 project, I get: {"Upgrade":true}

Actual behavior

When run as .NET 7 project (RC1), I get:

Unhandled exception. System.InvalidOperationException: The type 'System.ReadOnlySpan`1[System.Byte]' of property 'Span' on type 'System.ReadOnlyMemory`1[System.Byte]' is invalid for serialization or deserialization because it is a pointer type, is a ref struct, or contains generic parameters that have not been replaced by specific types.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_CannotSerializeInvalidType(Type typeToConvert, Type declaringType, MemberInfo memberInfo)
at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo`1.CreateProperty(Type typeToConvert, MemberInfo memberInfo, JsonSerializerOptions options, Boolean shouldCheckForRequiredKeyword)
at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo`1.CacheMember(Type typeToConvert, MemberInfo memberInfo, Boolean& propertyOrderSpecified, Dictionary`2& ignoredMembers, Boolean shouldCheckForRequiredKeyword)
at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo`1.AddPropertiesAndParametersUsingReflection()
at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo`1..ctor(JsonConverter converter, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.CreateReflectionJsonTypeInfo(JsonSerializerOptions options)
at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.CreateJsonTypeInfo(Type type, JsonSerializerOptions options)
at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetTypeInfo(Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.GetTypeInfoNoCaching(Type type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Boolean resolveIfMutable)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo.Configure()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.InitializePropertyCache()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure()
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.<EnsureConfigured>g__ConfigureLocked|138_0()
at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Boolean resolveIfMutable)
at System.Text.Json.JsonSerializer.GetTypeInfo(JsonSerializerOptions options, Type inputType)
at System.Text.Json.JsonSerializer.GetTypeInfo[T](JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
at JsonSerializeRepro.Program.Main(String[] args) in C:\Users\USER\JsonSerializeRepro\JsonSerializeRepro\Program.cs:line 14

Regression?

Maybe it's a regression. I'm not sure.

Known Workarounds

Implement custom JSON converter

usingSystem;usingSystem.Text.Json;usingSystem.Text.Json.Serialization;namespaceJsonSerializeRepro;publicstaticclassProgram{publicstaticvoidMain(string[]args){ReadOnlyMemory<byte>binaryData=Array.Empty<byte>();InstallScriptRequestinstallScriptRequest=new(binaryData,upgrade:true);JsonSerializerOptionsserializationOptions=new();serializationOptions.Converters.Add(newInstallScriptRequestConverter());stringjson=JsonSerializer.Serialize(installScriptRequest,serializationOptions);Console.WriteLine(json);}}publicclassInstallScriptRequestConverter:JsonConverter<InstallScriptRequest>{/// <inheritdoc/>publicoverrideInstallScriptRequestRead(refUtf8JsonReaderreader,TypetypeToConvert,JsonSerializerOptionsoptions){thrownewNotImplementedException();}/// <inheritdoc/>publicoverridevoidWrite(Utf8JsonWriterwriter,InstallScriptRequestvalue,JsonSerializerOptionsoptions){writer.WriteStartObject();writer.WritePropertyName("upgrade");writer.WriteBooleanValue(value.Upgrade);writer.WriteEndObject();}}publicclassInstallScriptRequest{/// <inheritdoc/>[JsonIgnore]publicintBinaryDataMaxSize=>1024*1024;/// <summary>ZIP archive that contains the script package to install.</summary>[JsonIgnore]publicReadOnlyMemory<byte>BinaryData{get;set;}publicboolUpgrade{get;}publicInstallScriptRequest(ReadOnlyMemory<byte>binaryData,boolupgrade){this.BinaryData=binaryData;this.Upgrade=upgrade;}}

Configuration

Tested on Windows 11. However, I don't believe it's a platform-specific issue.

Other information

No response

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions