DataContractJsonSerializer: Serializing and Deserializing enum values by their name

I am stuck in a project where I have to use the DataContractJsonSerializer coming with the .NET Framework. Serializing and Deserializing enum values by their name instead of their numerical value might not be obvious, so here is a simple example on how to do it.

First of all we'll define an interface for the Serializer.

namespace JsonExample.Serialization
{
    public interface ISerializer
    {
        string Serialize<TEntity>(TEntity entity)  
            where TEntity : class, new();  

        TEntity Deserialize<TEntity>(string entity) 
            where TEntity : class, new();   
    }
}

Next we'll implement a sample Json Serializer using the DataContractJsonSerializer.

using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

namespace JsonExample.Serialization
{
    public class JsonSerializer : ISerializer
    {
        public string Serialize<TEntity>(TEntity entity) 
            where TEntity : class, new()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TEntity));
                ser.WriteObject(ms, entity);
                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }

        public TEntity Deserialize<TEntity>(string entity) 
            where TEntity : class, new()
        {
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(TEntity));
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(entity)))
            {
                return ser.ReadObject(stream) as TEntity;
            }
        }
    }
}

Next we define the enum, which we want to serialize and deserialize to JSON.

namespace JsonExample.Model
{
    public enum SampleEnum
    {
        FirstValue = 0,
        SecondValue
    }
}

And then we'll define the class, that uses the SampleEnum. The trick is to use a string as a private property and override its getter and setter, so that:

  • The getter returns the name of the enum value when serializing it.
  • The setter parses the given enum name and sets the public property (EnumVal in this example)
using System;
using System.Runtime.Serialization;

namespace JsonExample.Model
{
    [DataContract]
    public class SampleClass
    {
        [DataMember(Name = "description", Order = 0)]
        public string Description { get; set; }

        public SampleEnum EnumVal { get; set; }

        [DataMember(Name = "enumVal", Order = 1)]
        private string EnumValString
        {
            get { return Enum.GetName(typeof(SampleEnum), this.EnumVal); }
            set { this.EnumVal = (SampleEnum)Enum.Parse(typeof(SampleEnum), value, true); }
        }
    }
}

And that's it basically. I am a big believer in Unit testing, so let's write a test to serialize and deserialize the sample class.

using NUnit.Framework;
using JsonExample.Model;
using JsonExample.Serialization;

namespace JsonExample
{
    [TestFixture]
    public class JsonSerializationTest
    {
        private ISerializer jsonSerializer;

        [SetUp]
        public void SetUp()
        {
            jsonSerializer = new JsonSerializer();
        }

        [Test]
        public void SerializeEnumValueTest()
        {
            SampleClass sampleEntity = new SampleClass 
            {
                Description = "SerializeTest",
                EnumVal = SampleEnum.FirstValue
            };

            string expectedJsonData = "{\"description\":\"SerializeTest\",\"enumVal\":\"FirstValue\"}";
            string actualJsonData = jsonSerializer.Serialize<SampleClass>(sampleEntity);

            Assert.AreEqual(expectedJsonData, actualJsonData);
        }

        [Test]
        public void DeserializeEnumValueTest()
        {
            string jsonData = "{\"description\":\"DeserializeTest\",\"enumVal\":\"SecondValue\"}";

            SampleClass expectedSampleEntity = new SampleClass
            {
                Description = "DeserializeTest",
                EnumVal = SampleEnum.SecondValue
            };

            SampleClass actualSampleEntity = jsonSerializer.Deserialize<SampleClass>(jsonData);

            Assert.AreEqual(expectedSampleEntity.Description, actualSampleEntity.Description);
            Assert.AreEqual(expectedSampleEntity.EnumVal, actualSampleEntity.EnumVal);
        }
    }
}

How to contribute

One of the easiest ways to contribute is to participate in discussions. You can also contribute by submitting pull requests.

General feedback and discussions?

Do you have questions or feedback on this article? Please create an issue on the GitHub issue tracker.

Something is wrong or missing?

There may be something wrong or missing in this article. If you want to help fixing it, then please make a Pull Request to this file on GitHub.