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);
}
}
}