Serializing enums as strings using System.Text.Json library in .NET Core 3.0
.NET Core 3.0 uses the System.Text.Json API by default for JSON serialization operations. Prior versions of .NET Core relied on JSON.NET, a third party library developed by Newtonsoft and the framework team decided to create a brand new library that can make use of the latest features in the language and the framework.
The new library has got support for all the new features that got introduced in the latest version of C#. And this was one of the main reasons behind the development of the new library because implementing these changes in JSON.NET meant a significant rewrite.
While serializing an object into JSON using the new library we can control various options such as casing, indentation, etc, but one notable omission is the support for enums by default. If you try to serialize an enum in .NET Core 3.0 with the default library, it will convert it into an integer value instead of the name of the enum.
For example, let consider the following model and see if what happens when we serialize it using the System.Text.Json library
public enum AddressType { HomeAddress, OfficeAddress, CommunicationAddress } public class Employee { public string FirstName { get; set; } public string LastName { get; set; } public AddressType CommunicationPreference { get; set; } }
and when you serialize it using the serialize method
Listemployees = new List { new Employee{ FirstName = "Amal", LastName ="Dev", CommunicationPreference = AddressType.HomeAddress }, new Employee{ FirstName = "Dev", LastName ="D", CommunicationPreference = AddressType.CommunicationAddress }, new Employee{ FirstName = "Tris", LastName ="Tru", CommunicationPreference = AddressType.OfficeAddress } } JsonSerializer.Serialize(employees);
it will produce an output like the one given below
[ { "FirstName":"Amal", "LastName":"Dev", "CommunicationPreference":0 }, { "FirstName":"Dev", "LastName":"D", "CommunicationPreference":2 }, { "FirstName":"Tris", "LastName":"Tru", "CommunicationPreference":1 } ]
If you look closely at the output string, the CommunicationPreference property has integer values instead of the names. In some scenarios, say if you are trying to give it as an output of an API method call it is not desirable to give back these integer values which can be meaningless. To overcome this, you can make use of a converter available in the library to do the conversion for you. To use this, instantiate an object of the JsonSerializerOptions and specify the converter there. And when you call the serialize method, pass this object also into that method as shown below
JsonSerializerOptions options = new JsonSerializerOptions{ Converters ={ new JsonStringEnumConverter() } }; JsonSerializer.Serialize(employees, options);
Now the generated output will be
[ { "FirstName":"Amal", "LastName":"Dev", "CommunicationPreference":"HomeAddress" }, { "FirstName":"Dev", "LastName":"D", "CommunicationPreference":"CommunicationAddress" }, { "FirstName":"Tris", "LastName":"Tru", "CommunicationPreference":"OfficeAddress" } ]
You will see now that our property is correctly displaying the names of the enums which is done automatically by the converter we added. By default, the library converts the strings to Pascal Case instead of the camelCase which is the most widely used format in JSON. You can control this behavior by specifying the format while hooking up the converter to the serializer
JsonSerializerOptions options = new JsonSerializerOptions{ Converters ={ new JsonStringEnumConverter( JsonNamingPolicy.CamelCase) }, };
And now, the output will be
[ { "FirstName":"Amal", "LastName":"Dev", "CommunicationPreference":"homeAddress" }, { "FirstName":"Dev", "LastName":"D", "CommunicationPreference":"communicationAddress" }, { "FirstName":"Tris", "LastName":"Tru", "CommunicationPreference":"officeAddress" } ]
Deserializing Enums as Strings
We can use the same converter for doing deserialization also. If we try to deserialize
string emp="[{\"FirstName\":\"Amal\",\"LastName\":\"Dev\",\"CommunicationPreference\":\"HomeAddress\"},{\"FirstName\":\"Dev\",\"LastName\":\"D\",\"CommunicationPreference\":\"CommunicationAddress\"},{\"FirstName\":\"Tris\",\"LastName\":\"Tru\",\"CommunicationPreference\":\"OfficeAddress\"}]";
Unhandled exception. System.Text.Json.JsonException: The JSON value could not be converted to JsonTextApi.AddressType. Path: $[0].CommunicationPreference
But, if
JsonSerializerOptions options = new JsonSerializerOptions{ Converters ={ new JsonStringEnumConverter( JsonNamingPolicy.CamelCase) }, }; JsonSerializer.Deserialize<List>(emp,options).ForEach(x=> Console.WriteLine($"{x.FirstName} {x.LastName}, {x.CommunicationPreference}"));
Output
Amal Dev, HomeAddress Dev D, CommunicationAddress Tris Tru, OfficeAddress
Part 1 : Serializing and Deserializing Json in .NET Core 3.0 using System.Text.Json API
Part 2: Step-By-Step Guide to Serialize and Deserialize JSON Using System.Text.Json
Part 3: Avoid conversion errors by using Custom Converters in System.Text.Json API
No Comments
Connecting Azure Blob Storage account using Managed Identity
Posted 12/9/2022Securing Azure KeyVault connections using Managed Identity
Posted 11/26/2022Manage application settings with Azure KeyVault
Posted 11/9/2022Adding Serilog to Azure Functions created using .NET 5
Posted 4/3/2021Learn how to split log data into different tables using Serilog in ASP.NET Core
Posted 4/23/2020