Transitioning Serialization and Deserialization Processes to matlab.mixin.CustomElementSerialization - MATLAB & Simulink (original) (raw)
The recommended process for customizing serialization and deserialization of objects is to use the matlab.mixin.CustomElementSerialization mixin (since R2024b). Transitioning to the mixin from an existing implementation of loadobj
andsaveobj
can give you greater control of the serialization process in future revisions of the class. However, some existing implementations might makeloadobj
and saveobj
the better option.
Preserve Version Compatibility Between loadobj
and saveobj
Implementations andmatlab.mixin.CustomElementSerialization
The first version of the Rectangle
class represents a rectangle using the coordinates of the lower-left and upper-right vertices. The saveobj
and loadobj
methods only handle the property data using structures. This implementation enables flexibility for any future class versions that use different properties to define the rectangle.
classdef Rectangle % Version 1
properties
x1
y1
x2
y2
end
methods
function obj = Rectangle(x1,y1,x2,y2)
obj.x1 = x1;
obj.y1 = y1;
obj.x2 = x2;
obj.y2 = y2;
end
function s = saveobj(obj)
s.x1 = obj.x1;
s.y1 = obj.y1;
s.x2 = obj.x2;
s.y2 = obj.y2;
end
end
methods(Static)
function obj = loadobj(s)
obj = Rectangle(s.x1,s.y1,s.x2,s.y2);
end
end
end
Version 2 of the class represents the rectangle using the coordinates of the lower-left vertex, the height, and the width. The revision maintains compatibility by implementing saveobj
and loadobj
methods to ensure that Version 2 of the class can load instances saved under Version 1, and Version 1 of the class can load instances saved under Version 2. The constructor accepts the same property values of Version 1, namely the coordinates of the lower-left and upper-right coordinates. The loadobj
method calls the Rectangle
constructor with those values. To preserve compatibility with Version 1, thesaveobj
method converts the new properties back to the old properties and saves them as a structure.
classdef Rectangle % Version 2
properties
x0
y0
width
height
end
methods
function obj = Rectangle(x1,y1,x2,y2)
obj.x0 = x1;
obj.y0 = y1;
obj.width = x2 - x1;
obj.height = y2 - y1;
end
function s = saveobj(obj)
s.x1 = obj.x0;
s.y1 = obj.y0;
s.x2 = obj.x0 + obj.width;
s.y2 = obj.y0 + obj.height;
end
end
methods(Static)
function obj = loadobj(s)
obj = Rectangle(s.x1,s.y1,s.x2,s.y2);
end
end
end
Version 2a of the Rectangle
class is a subclass ofmatlab.mixin.CustomElementSerialization
, but its behavior is consistent with Version 2. The modifyOutgoingSerializationContent
method stores the data in properties consistent with Version 1 of the class. With this method in place:
- Both Version 1 and Version 2 of the class can load instances saved under Version 2a because the property values are stored in the original format of Version 1.
modifyOutgoingSerializationContent
saves the rectangle information asx0
,y0
,width
, andheight
by default, but it also saves the coordinatesx1
,x2
,y1
, andy2
. Because Version 2a includes the properties and values in the same format as Versions 1 and 2, Version 2a can load an instance of any version.
classdef Rectangle < matlab.mixin.CustomElementSerialization % Version 2a
properties
x0
y0
width
height
end
methods
function obj = Rectangle(x1,y1,x2,y2)
obj.x0 = x1;
obj.y0 = y1;
obj.width = x2 - x1;
obj.height = y2 - y1;
end
end
methods(Static)
function modifyOutgoingSerializationContent(sObj,obj)
sObj.addNameValue("x1",obj.x0);
sObj.addNameValue("x2",obj.x0 + obj.width);
sObj.addNameValue("y1",obj.y0);
sObj.addNameValue("y2",obj.y0 + obj.height);
end
end
end
With this new version, you can now take advantage of all of the capabilities ofmatlab.mixin.CustomElementSerialization
. To check the compatibility, create an instance of Rectangle
under Version 2a.
test = Rectangle(1,1,4,6)
test =
Rectangle with properties:
x0: 1
y0: 1
width: 3
height: 5
Save the instance. modifyOutgoingSerializationContent
uses thewidth
and height
properties to define the second vertex.
save("yourfilepath/RectV2a.mat","test")
Clear the instance, and then load it under Version 1.
clear test load("yourfilepath/RectV2a.mat","test") test
test =
Rectangle with properties:
x1: 1
y1: 1
x2: 4
y2: 6
Private Properties with the Same Name in Class Hierarchies
Classes in a hierarchy that define private properties with the same name require special handling when serializing and deserializing with loadobj
andsaveobj
. The Animal
class and its subclassPet
both define a private property named ID
. To handle both properties:
- The
saveobj
method ofAnimal
saves itsID
property in the outgoing structure under the name ofAnimalID
to avoid conflicting with theID
property ofPet
. - The
loadobj
methods of both classes pass the value ofAnimalID
to the constructor to recreate theID
property ofAnimal
.
classdef Animal properties Species end properties(Access = private) ID end
methods
function obj = Animal(Species,ID)
obj.Species = Species;
obj.ID = ID;
end
function s = saveobj(obj)
s.Species = obj.Species;
s.AnimalID = obj.ID;
end
end
methods (Static)
function obj = loadobj(s)
if isstruct(s)
obj = Animal(s.Species,s.AnimalID);
else
obj = s;
end
end
end
end
classdef Pet < Animal properties OwnerName end properties(Access = private) ID end
methods
function obj = Pet(Species,AnimalID,OwnerName,ID)
obj@Animal(Species,AnimalID);
obj.OwnerName = OwnerName;
obj.ID = ID;
end
function s = saveobj(obj)
s = saveobj@Animal(obj);
s.OwnerName = obj.OwnerName;
s.ID = obj.ID;
end
end
methods(Static)
function obj = loadobj(s)
if isstruct(s)
obj = Pet(s.Species,s.AnimalID,s.OwnerName,s.ID);
else
obj = s;
end
end
end
end
The matlab.mixin.CustomElementSerialization
mixin enables you to reference private properties with the same name by preceding the property name with the name of the defining class and a dot. You can use this convention to transition classes with private property overlap to use the mixin instead of saveobj
andloadobj
.
For example, the following revised Animal
class inherits from the mixin and implements a modifyIncomingSerializationContent
method. Thesaveobj
method of the original Animal
stores itsID
property as AnimalID
. ThemodifyIncomingSerializationContent
method checks for anAnimalID
field in the incoming content. IfAnimalID
is part of the serialized content, themodifyIncomingSerializationContent
method renames the property toAnimal.ID
. The rename
method uses the_className.propertyName
_ syntax that is required for private properties. (For more information, see the description for rename
inmatlab.serialization.ElementSerializationContent.)
classdef Animal < matlab.mixin.CustomElementSerialization properties Species end properties (Access = private) ID end
methods
function obj = Animal(Species,ID)
obj.Species = Species;
obj.ID = ID;
end
end
methods(Static)
function modifyIncomingSerializationContent(sObj)
if sObj.hasNameValue("AnimalID")
sObj.rename("AnimalID","Animal.ID");
end
end
end
end
The revised Pet
class implements amodifyIncomingSerializationContent
method that calls the superclass method to process the superclass ID
property. To enable the older version of the class to deserialize objects saved under the new definition,Pet
implements modifyOutgoingSerializationContent
to save the superclass ID
property as AnimalID
.
classdef Pet < Animal properties OwnerName end properties(Access = private) ID end methods function obj = Pet(Species,AnimalID,OwnerName,ID) obj@Animal(Species,AnimalID); obj.OwnerName = OwnerName; obj.ID = ID; end end
methods(Static)
function modifyOutgoingSerializationContent(sObj,~)
sObj.addNameValue("AnimalID",sObj.getValue("Animal.ID"));
sObj.remove("Animal.ID");
end
function modifyIncomingSerializationContent(sObj)
modifyIncomingSerializationContent@Animal(sObj)
end
end
end
Maintaining Existing loadobj
and saveobj
Implementations
In some cases, existing designs using loadobj
andsaveobj
cannot be easily transitioned to amatlab.mixin.CustomElementSerialization
design without significant revision of existing classes. For example:
- The
loadobj
method of an existing class only accepts a structure as input. Deserializing an object under the old definition might cause warnings. To forceloadobj
to deserialize the content as a structure, you can usemodifyOutgoingSerializationContent
to add a property that is not part of the original class definition. The disadvantage to this method is that the added property is now stored, even though it has no meaning in either version of the class. - The
loadobj
method can only deserialize data from a format other than an object or a structure. For example, a class could usesaveobj
to save property values in a table, and the correspondingloadobj
can only accept a table as input. The methods ofmatlab.mixin.CustomElementSerialization
only support object data, so data from the older version of the class would be inaccessible. In this case, the only workaround is to revise how the existing class definition serializes data.
In cases like these, maintaining your existing loadobj
andsaveoobj
implementations might be preferable to what would be required to transition to matlab.mixin.CustomElementSerialization
.
See Also
matlab.mixin.CustomElementSerialization | matlab.serialization.ElementSerializationContent | matlab.serialization.SerializationContext