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:

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:

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:

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