-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
area-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additionsProduct code improvement that does NOT require public API changes/additions
Milestone
Description
Description
If you apply the [JsonConstructorAttribute] to more than one constructor, the runtime exception is:
System.InvalidOperationException
HResult=0x80131509
Message=The type 'ConsoleApp11.Program+Invoice' cannot have more than one property that has the attribute 'System.Attribute'.
Source=System.Text.Json
StackTrace:
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateTypeAttribute[TAttribute](Type classType)
at System.Text.Json.Serialization.Converters.ObjectConverterFactory.GetDeserializationConstructor(Type type)
at System.Text.Json.Serialization.Converters.ObjectConverterFactory.CreateConverter(Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverterFactory.GetConverterInternal(Type typeToConvert, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.GetConverterInternal(Type typeToConvert)
at System.Text.Json.JsonSerializerOptions.DetermineConverter(Type parentClassType, Type runtimePropertyType, MemberInfo memberInfo)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.GetConverter(Type type, Type parentClassType, MemberInfo memberInfo, Type& runtimeType, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.<RootBuiltInConvertersAndTypeInfoCreator>g__CreateJsonTypeInfo|107_0(Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializerOptions.GetClassFromContextOrCreate(Type type)
at System.Text.Json.JsonSerializerOptions.GetOrAddClass(Type type)
at System.Text.Json.JsonSerializerOptions.GetOrAddClassForRootType(Type type)
at System.Text.Json.JsonSerializer.GetTypeInfo(Type runtimeType, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Write[TValue](TValue& value, Type runtimeType, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)The Exception text is wrong:
- The attribute is not applied to properties at all
- The attribute type should reference the concrete type, not the base Attribute type.
The error message template should probably just be changed to say member instead of property.
The Throwhelper:
runtime/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs
Lines 422 to 425 in 57bfe47
| public static void ThrowInvalidOperationException_SerializationDuplicateTypeAttribute<TAttribute>(Type classType) | |
| { | |
| throw new InvalidOperationException(SR.Format(SR.SerializationDuplicateTypeAttribute, classType, typeof(Attribute))); | |
| } |
should be changed to use typeof(TAttribute) instead of typeof(Attribute) (I guess that was a typo).
This was found while looking at: #55318
Regression?
No, appears to happen in 5.0 too.
Other information
Repro:
class Program
{
static void Main(string[] args)
{
var invoice = new Invoice(new List<InvoiceItem>());
var serialized = JsonSerializer.Serialize(invoice);
var deserialized = JsonSerializer.Deserialize<Invoice>(serialized);
}
public class Invoice
{
private List<InvoiceItem> items;
public IReadOnlyCollection<InvoiceItem> Items => items;
[JsonConstructor]
public Invoice(List<InvoiceItem> items)
{
this.items = items;
}
[JsonConstructor]
[Obsolete]
public Invoice(IReadOnlyCollection<InvoiceItem> items)
{
this.items = items as List<InvoiceItem> ?? this.items.ToList();
}
public void AddItem(InvoiceItem invoiceItem)
{
//Some domain logic validation
items.Add(invoiceItem);
}
}
public class InvoiceItem
{ }
}Metadata
Metadata
Assignees
Labels
area-System.Text.JsonenhancementProduct code improvement that does NOT require public API changes/additionsProduct code improvement that does NOT require public API changes/additions