-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Description
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:
<Project Sdk="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:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JsonSerializeRepro;
public static class Program
{
public static void Main(string[] args)
{
ReadOnlyMemory<byte> binaryData = Array.Empty<byte>();
InstallScriptRequest installScriptRequest = new(binaryData, upgrade: true);
string json = JsonSerializer.Serialize(installScriptRequest);
Console.WriteLine(json);
}
}
public class InstallScriptRequest
{
[JsonIgnore]
public int BinaryDataMaxSize => 1024 * 1024;
[JsonIgnore]
public ReadOnlyMemory<byte> BinaryData { get; set; }
public bool Upgrade { get; }
public InstallScriptRequest(ReadOnlyMemory<byte> binaryData, bool upgrade)
{
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
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JsonSerializeRepro;
public static class Program
{
public static void Main(string[] args)
{
ReadOnlyMemory<byte> binaryData = Array.Empty<byte>();
InstallScriptRequest installScriptRequest = new(binaryData, upgrade: true);
JsonSerializerOptions serializationOptions = new();
serializationOptions.Converters.Add(new InstallScriptRequestConverter());
string json = JsonSerializer.Serialize(installScriptRequest, serializationOptions);
Console.WriteLine(json);
}
}
public class InstallScriptRequestConverter : JsonConverter<InstallScriptRequest>
{
/// <inheritdoc/>
public override InstallScriptRequest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
public override void Write(Utf8JsonWriter writer, InstallScriptRequest value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName("upgrade");
writer.WriteBooleanValue(value.Upgrade);
writer.WriteEndObject();
}
}
public class InstallScriptRequest
{
/// <inheritdoc/>
[JsonIgnore]
public int BinaryDataMaxSize => 1024 * 1024;
/// <summary>ZIP archive that contains the script package to install.</summary>
[JsonIgnore]
public ReadOnlyMemory<byte> BinaryData { get; set; }
public bool Upgrade { get; }
public InstallScriptRequest(ReadOnlyMemory<byte> binaryData, bool upgrade)
{
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