*
Previous Exception Handling and Logging in C# Generics in C# Next

🔄 Serialization and deserialization in C#

Serialization is the process of converting the state of an object into a form that can be easily stored or transmitted. This allows you to save an object to a file, send it over a network, or store it in a database. During serialization, the object's public properties and fields are converted into a format like JSON, XML, or a byte stream.

Deserialization is the reverse process. It takes the serialized data and reconstructs it back into an object in the application's memory.

🔄 Serialization in C#

Serialization is the process of converting an object into a format that can be stored or transmitted (e.g., JSON, XML, binary). The reverse process is called deserialization.

📚 Types of Serialization in C#

  • 1️⃣ Binary Serialization: Converts objects into binary format. Preserves full object state including private fields.
  • 2️⃣ XML Serialization: Converts objects into XML. Only public properties and fields are serialized.
  • 3️⃣ JSON Serialization: Converts objects into JSON format. Commonly used in web APIs and modern apps.
  • 4️⃣ SOAP Serialization: Serializes objects into SOAP messages. Used in legacy web services.
  • 5️⃣ Custom Serialization: Implements ISerializable for full control over the serialization process.

📦 JSON Serialization Example

  using System.Text.Json;

  public class Person {
      public string Name { get; set; }
      public int Age { get; set; }
  }

  var person = new Person { Name = "Alice", Age = 30 };
  string json = JsonSerializer.Serialize(person);
  var deserialized = JsonSerializer.Deserialize<Person>(json);
  

1. Binary Serialization

Binary serialization converts an object into a compact stream of bytes. It is efficient for storing data within the same .NET ecosystem but is not human-readable and lacks cross-platform compatibility. The BinaryFormatter class was historically used but is now obsolete due to security issues.

Example (for educational purposes only):

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

// The [Serializable] attribute is required for binary serialization.
[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class BinarySerializationExample
{
    public static void Run()
    {
        // --- Serialization ---
        var person = new Person { Name = "John Doe", Age = 30 };
        var formatter = new BinaryFormatter();
        using (var stream = new FileStream("person.dat", FileMode.Create))
        {
            // Note: BinaryFormatter is obsolete and not recommended for new projects.
            formatter.Serialize(stream, person);
        }
        Console.WriteLine("Binary serialization complete. Data saved to person.dat.");

        // --- Deserialization ---
        using (var stream = new FileStream("person.dat", FileMode.Open))
        {
            Person deserializedPerson = (Person)formatter.Deserialize(stream);
            Console.WriteLine("\nBinary deserialization complete.");
            Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
        }
    }
}

Use code with caution.

2. XML Serialization

XML serialization converts an object’s public properties and fields into a human-readable XML format. It is interoperable and can be easily consumed by other platforms. The XmlSerializer class is used for this purpose.

Example:

using System;
using System.IO;
using System.Xml.Serialization;

public class Employee
{
    public string Name { get; set; }
    public int EmployeeId { get; set; }
}

public class XmlSerializationExample
{
    public static void Run()
    {
        // --- Serialization ---
        var employee = new Employee { Name = "Jane Doe", EmployeeId = 101 };
        var serializer = new XmlSerializer(typeof(Employee));

        using (var writer = new StreamWriter("employee.xml"))
        {
            serializer.Serialize(writer, employee);
        }
        Console.WriteLine("XML serialization complete. Data saved to employee.xml.");

        // --- Deserialization ---
        using (var reader = new StreamReader("employee.xml"))
        {
            Employee? newEmployee = serializer.Deserialize(reader) as Employee;
            Console.WriteLine("\nXML deserialization complete.");
            Console.WriteLine($"Name: {newEmployee?.Name}, ID: {newEmployee?.EmployeeId}");
        }
    }
}

Use code with caution.

3. JSON Serialization

JSON serialization converts an object into a text-based JSON string. It is widely used in modern web APIs due to its readability and performance. The System.Text.Json namespace provides efficient serializers.

Example:

using System;
using System.Text.Json;

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class JsonSerializationExample
{
    public static void Run()
    {
        // --- Serialization ---
        var product = new Product { Name = "Laptop", Price = 1200.50m };
        string jsonString = JsonSerializer.Serialize(product);
        Console.WriteLine($"JSON serialization complete.\nJSON: {jsonString}");

        // --- Deserialization ---
        Product? newProduct = JsonSerializer.Deserialize<Product>(jsonString);
        Console.WriteLine("\nJSON deserialization complete.");
        Console.WriteLine($"Product: {newProduct?.Name}, Price: {newProduct?.Price}");
    }
}

Use code with caution.

4. SOAP Serialization

SOAP (Simple Object Access Protocol) serialization is an XML-based protocol for structured data exchange in web services. It has largely been replaced by REST and JSON. The SoapFormatter class, once used for this, is now obsolete and should be avoided in new applications.

5. Custom Serialization

Custom serialization allows developers to control how an object’s state is saved and restored. This is useful for complex data structures or special formats. In modern .NET, implementing a JsonConverter or the ISerializable interface is recommended.

Example: Custom JSON Converter

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

// The custom converter for 'Point'
public class PointConverter : JsonConverter<Point>
{
    public override Point Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // Custom deserialization logic
        if (reader.TokenType != JsonTokenType.StartArray)
            throw new JsonException();

        reader.Read();
        int x = reader.GetInt32();
        reader.Read();
        int y = reader.GetInt32();
        reader.Read();

        if (reader.TokenType != JsonTokenType.EndArray)
            throw new JsonException();

        return new Point(x, y);
    }

    public override void Write(Utf8JsonWriter writer, Point value, JsonSerializerOptions options)
    {
        // Custom serialization logic
        writer.WriteStartArray();
        writer.WriteNumberValue(value.X);
        writer.WriteNumberValue(value.Y);
        writer.WriteEndArray();
    }
}

// Apply the custom converter to the class
[JsonConverter(typeof(PointConverter))]
public class Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) => (X, Y) = (x, y);
}

public class CustomSerializationExample
{
    public static void Run()
    {
        // --- Serialization ---
        var point = new Point(10, 20);
        string json = JsonSerializer.Serialize(point);
        Console.WriteLine($"Custom JSON serialization complete.\nJSON: {json}");
        // Output: [10,20]

        // --- Deserialization ---
        Point newPoint = JsonSerializer.Deserialize<Point>(json);
        Console.WriteLine("\nCustom JSON deserialization complete.");
        Console.WriteLine($"Point: ({newPoint.X}, {newPoint.Y})");
    }
}

✅ Best Practices

  • Use System.Text.Json for modern JSON serialization.
  • Use XmlSerializer for interoperable XML formats.
  • Avoid BinaryFormatter in new code—it's obsolete and insecure.
  • Use [Serializable] and [NonSerialized] attributes appropriately.
  • Validate input before deserialization to prevent injection attacks.

📌 When to Use

  • To persist objects to disk or transmit over networks.
  • For APIs, config files, or inter-process communication.
  • When working with external systems that require structured formats.

🚫 When Not to Use

  • For large binary data—use streams or databases instead.
  • When performance is critical—serialization can add overhead.
  • For sensitive data—ensure encryption and secure transport.

⚠️ Precautions

  • Never deserialize untrusted data without validation.
  • Be cautious with circular references—they can break serialization.
  • Use try-catch to handle serialization errors gracefully.

🎯 Advantages

  • Interoperability: JSON and XML are widely supported.
  • Human-readable: Easy to debug and inspect.
  • Flexible: Supports custom mappings and nested structures.
  • Efficient: Lightweight formats for data exchange.

📝 Conclusion

Serialization in C# is essential for data exchange, persistence, and communication. Whether you're using JSON for APIs or XML for legacy systems, understanding the types and best practices ensures your applications are secure, efficient, and maintainable.

Back to Index
Previous Exception Handling and Logging in C# Generics in C# Next
*
*