Attributes For Record Properties In C# 9

Records provide a simple and easy for creating immutable objects, particularly when using Primary constructor. This reduces alot of boiler plate code. For example:
  1. public record User(string Name,DateTime DOB); 
 Now let's consider a situation where you want to serialize the User record, as shown in the following.
  1. "User""Anu Viswan""DateOfBirth""2020-11-20T00:00:00" } 
This would of course require us to decorate the Properties with JsonPropertyAttribute. With regular classes, or even with the non-primary constructor approach, we could have done the following:
  1. public record User  
  2. {  
  3.     [JsonProperty("User")]  
  4.     public string Name{get;init;}  
  5.   
  6.     [JsonProperty("DateOfBirth")]  
  7.     public DateTime Dob{get;init;}  

That works fine, however, if one would really wish to make use of the Primary constructor, one might be tempted to do the following:
  1. // This is wrong - it sets Attributes to the constructor parameter  
  2. public record User([JsonProperty("User")]string Name,[JsonProperty("DateOfBirth")]DateTime DOB); 
The above code sets the attributes to the constructor parameter, and not on the Property itself as one would have wished for. You could verify it by looking at the generated code in ILSpy.
  1. // Simplied code  
  2. public class User : IEquatable<User>  
  3. {  
  4.     public string Name  
  5.     {  
  6.         get;  
  7.         init;  
  8.     }  
  9.   
  10.     public DateTime DOB  
  11.     {  
  12.         get;  
  13.         init;  
  14.     }  
  15.   
  16.     public User([JsonProperty("User")] string Name, [JsonProperty("DateOfBirth")] DateTime DOB)  
  17.     {  
  18.         this.Name = Name;  
  19.         this.DOB = DOB;  
  20.         base..ctor();  
  21.     }  

Solution
 
The solution lies in specifying the target to which the attribute is applied to. This can be done using the property:. As noted in Microsoft documentation:
 
Attributes can be applied to the synthesized auto-property and its backing field by using property: or field: targets for attributes syntactically applied to the corresponding >record parameter.
 
Let's rewrite our record again:
  1. public record User([property:JsonProperty("User")]string Name,[property:JsonProperty("DateOfBirth")]DateTime DOB); 
Now if you inspect the generated code using ILSpy, you can verify that the attributes have been now applied to the Properties as desired. 
  1. // Simplied code 
  2. public class User : IEquatable<User>  
  3. {  
  4.     [JsonProperty("User")]  
  5.     public string Name  
  6.     {  
  7.         get;  
  8.         init;  
  9.     }  
  10.   
  11.     [JsonProperty("DateOfBirth")]  
  12.     public DateTime DOB  
  13.     {  
  14.         get;  
  15.         init;  
  16.     }  
  17.   
  18.     public User(string Name, DateTime DOB)  
  19.     {  
  20.         this.Name = Name;  
  21.         this.DOB = DOB;  
  22.         base..ctor();  
  23.     }  

You could now serialize your record to get the desired output.
  1. var data = new User("Anu Viswan",new DateTime(2020,11,20));  
  2. var serializedData = JsonConvert.SerializeObject(data);  
  3. // Output  
  4. {"User":"Anu Viswan","DateOfBirth":"2020-11-20T00:00:00"
On a closing note, if you replace property: with field:, the Attribute would be applied to the backing up field of the property.
Next Recommended Reading Caller Information Attributes in C# 5.0