Custom Serialization in C#
What is Custom Serialization in C#?
**Custom Serialization** allows developers to **control how an object is serialized and deserialized** instead of relying on the default behavior. This is useful when working with **private fields, complex objects, or version compatibility**.
Key Features of Custom Serialization
- Gives **full control** over the serialization process.
- Allows **excluding specific fields** dynamically.
- Useful for **handling private fields and encrypting data**.
- Supports **Binary, XML, and JSON serialization**.
Implementing Custom Serialization Using ISerializable
The **ISerializable** interface allows defining **custom serialization logic**.
Example: Custom Serialization Using ISerializable
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
class User : ISerializable
{
public string Username { get; set; }
private string Password { get; set; }
public User() { }
public User(string username, string password)
{
Username = username;
Password = password;
}
// Custom Serialization
protected User(SerializationInfo info, StreamingContext context)
{
Username = info.GetString("Username");
Password = Decrypt(info.GetString("Password"));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Username", Username);
info.AddValue("Password", Encrypt(Password));
}
private string Encrypt(string data) => $"encrypted({data})";
private string Decrypt(string data) => data.Replace("encrypted(", "").Replace(")", "");
public string GetPassword() => Password;
}
// Writing Custom Serialized Object
class Program
{
static void Main()
{
User user = new User("Alice", "SuperSecret123");
BinaryFormatter formatter = new BinaryFormatter();
using (FileStream stream = new FileStream("user.dat", FileMode.Create))
{
formatter.Serialize(stream, user);
}
Console.WriteLine("User object serialized with encryption.");
}
}
// Output:
// User object serialized with encryption.
The **ISerializable** interface allows **encrypting passwords** during serialization.
Custom JSON Serialization
The **System.Text.Json** library allows defining custom serialization using **JsonConverter**.
Example: Custom JSON Serialization Using JsonConverter
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
class User
{
public string Username { get; set; }
[JsonConverter(typeof(PasswordConverter))]
public string Password { get; set; }
}
// Custom Password Converter
class PasswordConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return $"decrypted({reader.GetString()})";
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
writer.WriteStringValue($"encrypted({value})");
}
}
// Writing Custom JSON Data
class Program
{
static void Main()
{
User user = new User { Username = "Bob", Password = "MySecret123" };
string json = JsonSerializer.Serialize(user);
Console.WriteLine("Serialized JSON:");
Console.WriteLine(json);
}
}
// Output:
// Serialized JSON:
// {"Username":"Bob","Password":"encrypted(MySecret123)"}
The **JsonConverter** class allows **encrypting and decrypting JSON fields**.
Custom XML Serialization
The **IXmlSerializable** interface allows defining **custom XML serialization** logic.
Example: Custom XML Serialization Using IXmlSerializable
using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
public class User : IXmlSerializable
{
public string Username { get; set; }
private string Password { get; set; }
public User() { }
public User(string username, string password)
{
Username = username;
Password = password;
}
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
Username = reader.GetAttribute("Username");
Password = Decrypt(reader.GetAttribute("Password"));
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("Username", Username);
writer.WriteAttributeString("Password", Encrypt(Password));
}
private string Encrypt(string data) => $"encrypted({data})";
private string Decrypt(string data) => data.Replace("encrypted(", "").Replace(")", "");
}
// Writing XML Data
class Program
{
static void Main()
{
User user = new User("Charlie", "Secret789");
XmlSerializer serializer = new XmlSerializer(typeof(User));
using (FileStream stream = new FileStream("user.xml", FileMode.Create))
{
serializer.Serialize(stream, user);
}
Console.WriteLine("User object serialized to XML.");
}
}
// Output:
// User object serialized to XML.
The **IXmlSerializable** interface allows **encrypting fields in XML serialization**.
Best Practices for Custom Serialization
- Use **ISerializable** for **BinaryFormatter** when private fields need serialization.
- For **JSON serialization**, use **JsonConverter** to **modify data** before storage.
- Use **IXmlSerializable** for **custom XML serialization logic**.
- Ensure **encryption or hashing** when dealing with **sensitive data**.