Are there any Delphi serialization libraries that are capable of serializing records and arrays of records instead of classes?
4 Answers
@Max you can use the TJvAppXMLFileStorage component from JEDI to serialize an record or an array of records.
you can use the procedure called WriteBinary
to store the data and ReadBinary
to read.
unfortunately there is not much documentation on this component, so here you have an very simple example for store a single record (for an array of records you can easily modify this source code).
The record structure
type
MyRecord= record
Field1 : Integer;
Field2 : Double;
Field3 : String[20];
Field4 : String[20];
end;
Save an record
Procedure SaveMyRecord(Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
//this component supports store multiples objects to the same file, so you need use an identifier for you particular object, in this case i'm use the Dummy name.
MyStore.WriteBinary('Dummy', @Rec,sizeof(Rec));
MyStore.Xml.SaveToFile(MyStore.FileName);
finally
MyStore.Free;
end;
end;
this procedure create an XML file like this, the data is encoded in an hexadecimal format.
<?xml version="1.0" encoding="iso-8859-1"?>
<Configuration>
<Dummy>84030000000000003333333333331F400D737472696E6720746573742031000000000000000D737472696E672074657374203200000000000000000000000000</Dummy>
</Configuration>
Read the persisted data
Procedure LoadMyRecord(var Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';//point to the same file
MyStore.Xml.LoadFromFile(MyStore.FileName); //load the file
MyStore.ReadBinary('Dummy', @Rec,sizeof(Rec));//use the Dummy identifier and pass the record as an pointer
finally
MyStore.Free;
end;
end;
Check this full project (tested in Delphi 7)
program ProjectPersistRecord;
{$APPTYPE CONSOLE}
uses
SysUtils,
JvAppXMLStorage;
type
MyRecord= record
Field1 : Integer;
Field2 : Double;
Field3 : String[20];
Field4 : String[20];
end;
Procedure SaveMyRecord(Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
MyStore.WriteBinary('Dummy', @Rec,sizeof(Rec));
MyStore.Xml.SaveToFile(MyStore.FileName);
finally
MyStore.Free;
end;
end;
Procedure LoadMyRecord(var Rec : MyRecord);
var
MyStore: TJvAppXMLFileStorage;
begin
MyStore:= TJvAppXMLFileStorage.Create(nil);
try
MyStore.FileName:='C:\temp\record.xml';
MyStore.Xml.LoadFromFile(MyStore.FileName);
MyStore.ReadBinary('Dummy', @Rec,sizeof(Rec));
finally
MyStore.Free;
end;
end;
Var
Rec : MyRecord;
begin
//Fill the record
Rec.Field1:=900;
Rec.Field2:=7.8;
Rec.Field3:='string test 1';
Rec.Field4:='string test 2';
SaveMyRecord(Rec); //save the record
FillChar(Rec,SizeOf(Rec),#0); //clear the record variable
LoadMyRecord(Rec);//restire the record data
//show the loaded data
Writeln(rec.field1);
Writeln(rec.field2);
Writeln(rec.field3);
Writeln(rec.field4);
Readln;
end.

- 134,889
- 20
- 356
- 483
-
284030000000000003333333333331F400D737472696E6720746573742031000000000000000D737472696E672074657374203200000000000000000000000000 maybe contains an Integer, a Double and two string[20], maybe not :) - Why not use a data transfer object to serialize to a real XML file, which is typesafe and supports versioning / compatibility, and also adds an "anti-corruption layer"? – mjn Jun 07 '10 at 20:01
-
1Binary content to XML. A perfect $$$$-storm of bad design decisions. Skip the XML if you're going to go binary. – Warren P Jun 10 '10 at 19:37
-
@Warren XML adds the comfort of having a standard way of separating the binary data, and may also contain metadata like attributes. It is very robust regarding structure changes and also human readable (if the element names have self-documenting names) – mjn Mar 30 '11 at 08:04
-
Much better to write an RTTI-based Record-persistence layer that writes XML or JSON out and skip the binary here. This ain't no Picture we're transferring, it's a few integers and other scalar and string types. – Warren P Jul 12 '12 at 02:31
Another solution, working from Delphi 5 up to XE2, is available in one of our OpenSource unit.
In fact, it implements:
- Some low-level RTTI functions for handling record types:
RecordEquals, RecordSave, RecordSaveLength, RecordLoad
; - A dedicated
TDynArray
object, which is a wrapper around any dynamic array, able to expose TList-like methods around any dynamic array, even containing records, strings, or other dynamic arrays. It's able to serialize any dynamic array.
Serialization uses an optimized binary format, and is able to save and load any record or dynamic array as RawByteString
. You have also JSON serialization at hand, including custom layout - see sustom JSON serialization of records.

- 42,305
- 3
- 71
- 159
-
update: the current version of the library will use the enhanced RTTI available since Delphi 2010 to serialize as JSON records and dynamic array contents. See http://blog.synopse.info/post/2014/05/18/Automatic-JSON-serialization-of-record-or-dynamic-arrays-via-Enhanced-RTTI And the library is still heavily maintained, tested with XE6 on Win32 and Win64 platforms. For older versions of Delphi, you can define your record as plain text, since the standard RTTI does not provide enough information. – Arnaud Bouchez Jun 10 '14 at 11:02
If you have Delphi 2010, you might want to take a look at DeHL. It contains a serialization library that can handle pretty much any data type.

- 82,511
- 50
- 270
- 477
-
Just small note, that you can also do (de)serialization of ANY records/dynamic arrays in older Delphi versions too (of course pointers/interfaces/classes won't serialized, there is no such info in RTTI for records/dyn. arrays). I didn't saw any library for it, but made it some time ago. Hint: System.pas - _FinalizeXxx/_InitializeXxx – Krystian Bigaj Jun 06 '10 at 15:55
Being a record, if you don't have properties, I don't believe you're any further ahead, trying to use any of the persistence frameworks (like DeHL).
The accepted answer, while technically correct, is dubious in real-world utility, and has many long term support-nightmare scenarios if you use it in production. DON'T DO IT.
If your program is just a bit of ad-hoc'ery, may I humbly suggest that you rock it old-school with a "file of record", a classic Turbo Pascal technique that still works.

- 65,725
- 40
- 181
- 316
-
-
Unfortunately file types do not support arrays. BTW the code that uses serialization does not go into production. This is just for the debugging. In particular I'm saving the result of the lengthy calculation, so I can load these results and start debugging a little faster. But it's a good tip, thanks. +1 – Max Jun 11 '10 at 00:40
-
Storing binary data inside XML has no advantage, and many real disadvantages as compared to just storing direct binary data either using `File Of Record` old-school, or a simple record-binary-writing-to-stream. – Warren P Oct 31 '12 at 20:34