Skip to main content

Serialization

Serialization converts an object's state into a byte stream so it can be persisted to storage, sent over a network, or otherwise transported. Deserialization reverses the process — turning a byte stream back into a live object. TinyCLR supports three serialization formats:

  • Binary — fast, compact, TinyCLR-internal format. Best when both sides are TinyCLR.
  • JSON — text or BSON, broadly compatible with any platform.
  • XML — structured text, useful for configuration files and interop with legacy systems.

Binary serialization

The native binary serializer is the fastest and most compact option for storing objects to flash or sending them between TinyCLR devices. It uses runtime reflection to walk the object's fields.

NuGet package: GHIElectronics.TinyCLR.Core (reflection-based serializer is part of the core).

using System;
using System.Diagnostics;
using System.Reflection;

public enum MyEnum : short { A, B, C }

[Serializable]
public class MySerializableClass {
public int a;
public string b;
private byte c;
private MyEnum d;
private float e;
private DateTime dt;

public MySerializableClass() { } // Parameterless constructor needed for deserialization.

public MySerializableClass(int a, string b, byte c, MyEnum d, float e) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.e = e;
this.dt = new DateTime(2026, 1, 22);
}

public override string ToString() =>
"a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", e=" + e.ToString("F2");
}

var original = new MySerializableClass(1, "ABCD", 3, MyEnum.B, 0.1f);
Debug.WriteLine("Original: " + original);

byte[] buffer = Reflection.Serialize(original, typeof(MySerializableClass));

var restored = (MySerializableClass)Reflection.Deserialize(buffer, typeof(MySerializableClass));
Debug.WriteLine("Restored: " + restored);
Debug.WriteLine("Bytes: " + buffer.Length);
note

The TinyCLR binary format is not wire-compatible with full .NET's BinaryFormatter out of the box. If you need PC↔device interop, you have two options:

  • Use JSON — simplest path, works with any platform and language.
  • Use a desktop bridge — the BinarySerializationDesktopSample repo on GitHub shows how to read TinyCLR-serialized binary on a desktop PC. Useful when you want compact binary on the wire but still need PC tooling to read it.
warning

GHI Electronics doesn't own or maintain the Apress/exp-.net-micro-framework repository linked above. It's published under its own license — review and comply with the license terms before using the code in your own projects.

JSON

JSON works across every platform that can speak HTTP — making it the natural choice for cloud integrations, web APIs, and PC tools. TinyCLR's JSON library also supports BSON (binary JSON), which is more compact on the wire.

NuGet package: GHIElectronics.TinyCLR.Data.Json.

using GHIElectronics.TinyCLR.Data.Json;
using System.Diagnostics;

// Serialize to JSON text.
var intArray = new int[] { 1, 3, 5, 7, 9 };
var jsonText = JsonConverter.Serialize(intArray).ToString();
Debug.WriteLine(jsonText); // "[1,3,5,7,9]"

// Round-trip through BSON (binary JSON).
var bson = JsonConverter.Serialize(intArray).ToBson();
var restored = (int[])JsonConverter.FromBson(bson, typeof(int[]));

for (var i = 0; i < intArray.Length; i++) {
if (intArray[i] != restored[i]) {
Debug.WriteLine("Array round-trip failed at index " + i);
return;
}
}
Debug.WriteLine("Array round-trip succeeded");

The same Serialize / FromBson pattern works for any class with public fields or properties — TinyCLR walks the type via reflection.

XML

TinyCLR includes XmlReader and XmlWriter for reading and writing XML — the standard streaming API from .NET. Useful for configuration files, structured logs, or interop with legacy systems that expect XML.

NuGet package: GHIElectronics.TinyCLR.Data.Xml.

note

TinyCLR's XML is not fully .NET-compatible — the asynchronous API isn't supported. For the full API surface, see Microsoft's System.Xml documentation.

Both XmlReader and XmlWriter implement IDisposable. Use using blocks to ensure they're closed properly.

The example below writes a small XML document to a memory stream, then reads it back:

using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;

// Write the XML.
var stream = new MemoryStream();
using (var writer = XmlWriter.Create(stream)) {
writer.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
writer.WriteComment("Sample logger configuration");
writer.WriteStartElement("DataLogger");
writer.WriteElementString("FileName", "Data");
writer.WriteElementString("FileExt", "txt");
writer.WriteElementString("SampleFrequency", "10");
writer.WriteEndElement();
writer.Flush();
}

byte[] xmlBytes = stream.ToArray();
Debug.WriteLine(Encoding.UTF8.GetString(xmlBytes));

// Read the XML back.
using (var readStream = new MemoryStream(xmlBytes))
using (var reader = XmlReader.Create(readStream, new XmlReaderSettings {
IgnoreWhitespace = true,
IgnoreComments = false,
})) {
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.Element:
Debug.WriteLine("Element: " + reader.Name);
break;
case XmlNodeType.Text:
Debug.WriteLine("Text: " + reader.Value);
break;
case XmlNodeType.Comment:
Debug.WriteLine("Comment: " + reader.Value);
break;
case XmlNodeType.XmlDeclaration:
Debug.WriteLine("Declaration: " + reader.Name + " " + reader.Value);
break;
case XmlNodeType.EndElement:
Debug.WriteLine("End: " + reader.Name);
break;
}
}
}

The WriteElementString(name, value) helper is much cleaner than the original verbose pattern (WriteStartElementWriteStringWriteEndElement) when you don't need to write attributes.

API reference

NamespaceDescription
GHIElectronics.TinyCLR.Data.JsonJSON serialization and deserialization classes