How to specify a sub-set of properties to serialize using custom attributes?

Viewed 28

C# I have a large class with many properties. There are different groups of properties that I sometimes want to update together, but do not want to send the entire object in a request.

Is there an easy way to use JsonSerializer and have it only select properties for serialization with specific attributes?

I would like to do something like JsonSerializer.Serialize(myclass, [CustomNameAttribute]) where it would only pull out UserFirstName and UserLastName. And preferably where I could specify a list of attributes to extract.

public class MyClass{
    [CustomNameAttribute]
    public string UserFirstName {get;set;}

    [CustomNameAttribute]
    public string UserLastName {get;set;}

    [CustomAddressAttribute]
    public string UserAddressLine1 {get;set;}

    [CustomAddressAttribute]
    public string UserAddressLine2 {get;set;}

    ...
}
1 Answers

My preferred solution is to use dedicated DTOs rather than depend on the serializer.

When using different specialized DTOs it is easier to ensure that unwanted data doesn't leak out, because it's easier to write a unit test for it. When you depend on json serialiser your test needs to include your full asp.net stack so that you can inspect the json.

Another benefit of using specialised DTOs is that naturally allows easier refactoring and optimising. It is easier to analyse the code if you know earlier (closer to the data source) that only specific fields are needed for a given path.

Even if you want to slim the objects at the last possible point I think a dedicated DTO can be the way to go. Here is one of many ways to go this path:

public class MySlimClass1 {

    public string UserFirstName {get;set;}

    public string UserLastName {get;set;}
}

public class MyBigClass{

    public string UserFirstName {get;set;}

    public string UserLastName {get;set;}

    public string UserAddressLine1 {get;set;}

    public string UserAddressLine2 {get;set;}

    public MySlimClass1 AsSlim() => new MySlimClass1 { UserFirstName, UserLastName };
}

Yyou could also make your class support multiple interfaces and serialise the interface(s), but:

  1. interfaces on dts are frowned upon
  2. ensuring the serialiser only serialises the interface properties depends on the serialiser (Json.NET vs System.Text.Json) and if done incorrectly may leak data.
Related