DEV Community

Peyman
Peyman

Posted on • Edited on

There should be a general-purpose attribute to customize JSON property names in .NET

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:

{
    "id": 1,
    "name": "Peyman",
    "create_date": "2021-07-14T00:00:00"
}
Enter fullscreen mode Exit fullscreen mode

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:

public class Person
{
    public int id { get; set; }
    public string name { get; set; }
    public DateTime create_date { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

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

To solve this issue, in Json.NET we have a JsonPropertyAttribute to specify the property name for serialization and de-serialization purposes.

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; }
}
Enter fullscreen mode Exit fullscreen mode

We can also use the built-in attributes such as DataContractAttribute, DataMemberAttribute instead of Json.NET's own attributes:

[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; }
}
Enter fullscreen mode Exit fullscreen mode

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:

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; }
}
Enter fullscreen mode Exit fullscreen mode

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.

Comment for #30009

hmqgg avatar
hmqgg commented on

Is there a particular reason why the new JsonPropertyName attribute won't work for your scenario?

For example, if we build a Blazor app, and ofc we'd like to make JSON models shared between our server and client to keep them consistent, but on the client side (i.e. Blazor project), we can't use System.Text.Json due to the runtime restrictions so we can't use JsonPropertyName.

What's more, many existing projects now use DataContract/DataMember attributes because it's common and most of JSON libs respect it.

I knew that now it's life after WCF, and we'd better not use these attributes introduced by WCF since it's nearly EoS. But we need attributes that could describe JSON models across so many JSON libs and runtime.

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

Comment for #29975

ahsonkhan avatar
ahsonkhan commented on

We don't currently have plans to support the attributes from System.Runtime.Serialization

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

See also:

Top comments (0)