Firstly, you only have to do this when you create your own constructors. This is due to the fact that on instantiation it won’t know which one to use.
Secondly, note that (by default) the deserializer will use the property and constructor names and overwrite the ones you omit in the actual constructor type. Furthermore, each parameter in the constructor must bind to an object property or field on deserialization. The formers can lead to subtle errors if you are not aware of them, however this is not limited solely to records.
All that aside, you had the attribute in the wrong place. In short, the attribute needs to be on the constructor.
Wildly contrived nonsensical example:
Given
public record TestRecord(Guid Id)
{
[JsonConstructor]
public TestRecord(object theThing, string whatHappened) : this(Guid.NewGuid())
{
}
}
Test
var record = new TestRecord(Guid.NewGuid());
var json = JsonConvert.SerializeObject(record,Formatting.Indented);
Console.WriteLine(json);
var otherSideRecord = JsonConvert.DeserializeObject<TestRecord>(json);
// note this paradoxically still works, because it has overwritten the ID
Console.WriteLine(record == otherSideRecord);
Ouput
{
"Id": "2905cfaf-d13d-4df1-af83-e4dcde20d44f"
}
True
Note that the attribute also works with Text.Json
var json = JsonSerializer.Serialize(record);
var otherSideRecord = JsonSerializer.Deserialize<TestRecord>(json);