Transitioning Serialization and Deserialization Processes to
matlab.mixin.CustomElementSerialization
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 and
saveobj can give you greater control of the serialization process in
future revisions of the class. However, some existing implementations might make
loadobj and saveobj the better option.
Preserve Version Compatibility Between loadobj and saveobj Implementations and
matlab.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, the
saveobj 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 of
matlab.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.
modifyOutgoingSerializationContentsaves the rectangle information asx0,y0,width, andheightby 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 of
matlab.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: 5Save the instance. modifyOutgoingSerializationContent uses the
width 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")
testtest =
Rectangle with properties:
x1: 1
y1: 1
x2: 4
y2: 6Private 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 and
saveobj. The Animal class and its subclass
Pet both define a private property named ID. To
handle both properties:
The
saveobjmethod ofAnimalsaves itsIDproperty in the outgoing structure under the name ofAnimalIDto avoid conflicting with theIDproperty ofPet.The
loadobjmethods of both classes pass the value ofAnimalIDto the constructor to recreate theIDproperty 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 and
loadobj.
For example, the following revised Animal class inherits from the
mixin and implements a modifyIncomingSerializationContent method. The
saveobj method of the original Animal stores its
ID property as AnimalID. The
modifyIncomingSerializationContent method checks for an
AnimalID field in the incoming content. If
AnimalID is part of the serialized content, the
modifyIncomingSerializationContent method renames the property to
Animal.ID. The rename method uses the
className.propertyName syntax that is required for private
properties. (For more information, see the description for rename in
matlab.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
Pet class implements a
modifyIncomingSerializationContent 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 and
saveobj cannot be easily transitioned to a
matlab.mixin.CustomElementSerialization design without significant
revision of existing classes. For example:
The
loadobjmethod of an existing class only accepts a structure as input. Deserializing an object under the old definition might cause warnings. To forceloadobjto deserialize the content as a structure, you can usemodifyOutgoingSerializationContentto 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
loadobjmethod can only deserialize data from a format other than an object or a structure. For example, a class could usesaveobjto save property values in a table, and the correspondingloadobjcan only accept a table as input. The methods ofmatlab.mixin.CustomElementSerializationonly 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 and
saveoobj 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