Conditional Serialization using NewtonSoft Json

One of the least explored feature of Newtonsoft Json is the ability serialize properties conditionally. Consider the hypothetical situation wherein you want to serialize a property in a class only if a condition is satisfied. For example,

public class User
{
public string Name {get;set;}
public string Department {get;set;}
public bool IsActive {get;set;}
}

If the requirement is that you need to include serialize the Department Property only if the User Is Active, then the easiest way to do it would be to use the Conditional Serialization functionality of Json.Net. All you need to do is include a method that
a) Returns a boolean indicating whether to serialize or not.
b) Should be named with Property named prefixed with ‘ShouldSerialize’

For example, for the Property Department, the method should be named ‘ShouldSerializeDepartment’. Example,

public bool ShouldSerializeDepartment()=> IsActive;

Complete Code

public class User
{
public string Name {get;set;}
public string Department{get;set;}
public bool IsActive {get;set;}
public bool ShouldSerializeDepartment()=> IsActive;
}

Client Code

var user = new User{ Name = "Anu Viswan", IsActive = false} ;
var result = JsonConvert.SerializeObject(user);

Output

{"Name":"Anu Viswan","IsActive":false}

Serializing/Deserializing Dictionaries with Tuple as Key

Sometimes you run into things that might look trivial but it just do not work as expected. One such example is when you attempt to serialize/Deserialize a Dictionary with Tuples as the key. For example

var dictionary = new Dictionary<(string, string), int>
{
[("firstName1", "lastName1")] = 5,
[("firstName2", "lastName2")] = 5
};

var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

The above code would trow an JsonSerializationException when deserializing. But the good part is, the exception tells you exactly what needs to be done. You need to use an TypeConverter here.

Let’s define our required TypeConverter

public class TupleConverter<T1, T2> : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var elements = Convert.ToString(value).Trim('(').Trim(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return (elements.First(), elements.Last());
}
}

And now, you can alter the above code as

TypeDescriptor.AddAttributes(typeof((string, string)), new TypeConverterAttribute(typeof(TupleConverter<string, string>)));
var json = JsonConvert.SerializeObject(dictionary);
var result = JsonConvert.DeserializeObject<Dictionary<(string, string), string>>(json);

With the magic portion of TypeConverter in place, your code would now work fine. Happy Coding.

Quick Intro to Protobuf

Protobuf-net is a .net adaption of Google’s Protocol Buffers and is generally considered to be a really fast serialization/deserialization library.  The target serializable classes are decorated with mainly 3 attributes.

ProtoContract
The target class is decorated with the ProtoContract attributes, indicating that the class can be serialized.

ProtoMember(N)
The ProtoMember attribute indicates the field that will be serialized, while the number N denotes the order in which the property would be serialized. By default, the properties would be serialized in alphabetical order.

ProtoIgnore
As the name suggests, the ProtoIgnore attributes is used to indicate the properties that needs to be ignored while serializing.

Let’s create the example class which we would be serializing.

[ProtoContract]
public class Student
{
  [ProtoMember(1)]
  public string Name { get; set; }
}

In order to serialize the class, you would be using the Static method Serialize.

var stOriginal = new Student() { Name = "jia" };
byte[] array;
           
using (var stream = new System.IO.MemoryStream())
{
   ProtoBuf.Serializer.Serialize(stream, stOriginal);
   array = stream.ToArray();
}

Similarly, the static method Deserialize can be used to deserialize the object back.

Student stDeserialized;
using (var stream = new System.IO.MemoryStream(array))
{
  stDeserialized = ProtoBuf.Serializer.Deserialize(stream);
}

Easy as that !! Happy Coding !!

Serialize Deserialize NameValueCollection

Don’t ask me why one cannot Serialize/Deserialize a NameValueCollection, but the workaround for the same is based on conversion to dictionary. I ended up writing extension methods to NameValueCollection for serializing and deserializing the collection.

public static string JSONSerialize(this NameValueCollection _nvc)
{
return JsonConvert.SerializeObject(_nvc.AllKeys.ToDictionary(k => k, k =>_nvc.GetValues(k)));
}
public static void JSONDeserialize(this NameValueCollection _nvc,string _serializedString)
{
var deserializedobject = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(_serializedString);
foreach (var strCol in deserializedobject.Values)
foreach (var str in strCol)
_nvc.Add(deserializedobject.FirstOrDefault(x => x.Value.Contains(str)).Key, str);
}