There should be a general-purpose attribute to customize JSON property names in .NET
Tags: dotnet, json, csharp
Published: 2021-07-13 22:26:29

Sometimes JSON property names can be very difficult to deal with; There are too many styles and too many libraries in between. Let's start with an example to fully understand the issue.

Consider the following JSON for a person:
```json
{
    "id": 1,
    "name": "Peyman",
    "create_date": "2021-07-14T00:00:00"
}
```
If we use the `Edit > Paste Special > Paste JSON As Classes` functionality in Visual Studio to paste the above JSON, it will generate a class like this:

```csharp
public class Person
{
    public int id { get; set; }
    public string name { get; set; }
    public DateTime create_date { get; set; }
}
```
As you can see, Visual Studio used the original property names and now we have some messages telling us that we have violated the naming rules.

![Visual Studio tells us that we have a naming rule violation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p0l471rgv5vtoi5va9m1.png)
 
To solve this issue, in [Json.NET][json-net] we have a `JsonPropertyAttribute` to specify the property name for serialization and de-serialization purposes.

```csharp
public class Person
{
    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("create_date")]
    public DateTime CreateDate { get; set; }
}
```
We can also use the built-in attributes such as `DataContractAttribute`, `DataMemberAttribute` instead of Json.NET's own attributes: 

```csharp
[DataContract]
public class Person
{
    [DataMember(Name = "id")]
    public int Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "create_date")]
    public DateTime CreateDate { get; set; }
}
```
This would be useful in scenarios where you don't want to depend on Json.NET's attributes.

Similarly, `System.Text.Json` has its own attributes:

```csharp
public class Person
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("name")]
    public string Name { get; set; }

    [JsonPropertyName("create_date")]
    public DateTime CreateDate { get; set; }
}
```
But strangely, `System.Text.Json` doesn't support `DataContract` and `DataMember` attributes. This brings us to the main point of this post:

> **The `System.Text.Json` or any major JSON libraries should support `DataContract` and `DataMember` attributes.**

By adding this feature, we can have a library-agnostic attribute that can be used by any tool out there to generate classes from JSON strings.

Another benefit of this feature would be if for some reason you wanted to switch between JSON libraries, you don't have to perform major changes to your classes since the new JSON library would use the same attributes. 

{% github https://github.com/dotnet/runtime/issues/30009#issuecomment-536344556 %}

As far as I can tell the .NET team has no intention to add this feature or introducing another attribute.

{% github https://github.com/dotnet/runtime/issues/29975#issuecomment-504610564 %}

Please head to [this issue on GitHub][1] and join the conversation and vote!

**See also:**
- [JsonSerializer should respect DataMemberAttribute.Name][2]
- [Paste JSON as Classes - Add option for C# naming conventions][3]
- [How to customize property names and values with System.Text.Json][4]
- [Serialization Attributes in Json.NET][5]
- [DataContract and DataMember Attributes in Json.NET][6]

[json-net]: https://www.newtonsoft.com/json
[1]: https://github.com/dotnet/runtime/issues/29975
[2]: https://github.com/dotnet/runtime/issues/30009
[3]: https://developercommunity.visualstudio.com/t/paste-json-as-classes-add-option-for-c-naming-conv/379864
[4]: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties
[5]: https://www.newtonsoft.com/json/help/html/SerializationAttributes.htm
[6]: https://www.newtonsoft.com/json/help/html/DataContractAndDataMember.htm