Records provide a simple and easy for creating immutable objects,
particularly when using Primary constructor. This reduces alot of boiler
plate code. For example:
- 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.
- { "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:
- public record User
- {
- [JsonProperty("User")]
- public string Name{get;init;}
-
- [JsonProperty("DateOfBirth")]
- 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:
-
- 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.
-
- public class User : IEquatable<User>
- {
- public string Name
- {
- get;
- init;
- }
-
- public DateTime DOB
- {
- get;
- init;
- }
-
- public User([JsonProperty("User")] string Name, [JsonProperty("DateOfBirth")] DateTime DOB)
- {
- this.Name = Name;
- this.DOB = DOB;
- base..ctor();
- }
- }
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:
- 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.
-
- public class User : IEquatable<User>
- {
- [JsonProperty("User")]
- public string Name
- {
- get;
- init;
- }
-
- [JsonProperty("DateOfBirth")]
- public DateTime DOB
- {
- get;
- init;
- }
-
- public User(string Name, DateTime DOB)
- {
- this.Name = Name;
- this.DOB = DOB;
- base..ctor();
- }
- }
You could now serialize your record to get the desired output.
- var data = new User("Anu Viswan",new DateTime(2020,11,20));
- var serializedData = JsonConvert.SerializeObject(data);
-
- {"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.