- A base class can’t legally set private/protected properties of subclasses unless it is given explicit access from “Property Access List”.
- To deserialize private properties, each class needs to define its own loading logic
- You can either loop manually over struct fields or use set if you inherit from matlab.mixin.SetGet for deserialization logic.
- You can decouple the looping logic into a helper, but the assignment must still happen inside each class.
Is custom generalized object serialization possible in Matlab?
    6 vues (au cours des 30 derniers jours)
  
       Afficher commentaires plus anciens
    
Cross-posting from here: http://stackoverflow.com/questions/12830716/is-custom-generalized-object-serialization-possible-in-matlab
I would like to save my objects as XML so that other applications can read from and write to the data files -- something that is very difficult with Matlab's binary mat files.
The underlying problem I'm running into is that Matlab's equivalent of reflection (which I've used to do similar things in .NET) is not very functional with respect to private properties. Matlab's struct(object) function offers a hack in terms of writing XML from an object because while I can't do
x = myInstance.myPrivateProperty;
...I can do
props = struct(myInstance);
x = props.myPrivateProperty;
So, I can create a pure (contains no objects) struct from any object using the code below, and then it's trivial to write an XML file using a pure struct.
But, is there any way to reverse the process? That is, to create an object instance using the data saved by the code below (that data contains a list of all non-Dependent, non-Constant, non-Transient properties of the class instance, and the name of the class)? I was thinking about having all my objects inherit from a class called XmlSerializable which would accept a struct as a single argument in the constructor and then assign all the values contained in the struct to the correspondingly-named properties. But, this doesn't work because if MyClass inherits XmlSerializable, the code in XmlSerializable isn't allowed to set the private properties of MyClass (related to How can I write generalized functions to manipulate private properties?). This would be no problem in .NET (See Is it possible to set private property via reflection), but I'm having trouble figuring it out in Matlab.
This code creates a struct that contains all of the state information for the object(s) passed in, yet contains no object instances. The resulting struct can be trivially written to XML:
function s = toPureStruct(thing)
    if isstruct(thing)
        s = collapseObjects(thing);
        s.classname = 'struct';
    elseif isobject(thing)
        s.classname = class(thing);
        warning off MATLAB:structOnObject;
        allprops = struct(thing);
        warning on MATLAB:structOnObject
        mc = metaclass(thing);
        for i=1:length(mc.PropertyList)
            p = mc.PropertyList(i);
            if strcmp(p.Name, 'classname')
                error('toStruct:PropertyNameCollision', 'Objects used in toStruct may not have a property named ''classname''');
            end
            if ~(p.Dependent || p.Constant || p.Transient)
                if isobject(allprops.(p.Name))
                    s.(p.Name) = toPureStruct(allprops.(p.Name));
                elseif isstruct(allprops.(p.Name))
                    s.(p.Name) = collapseObjects(allprops.(p.Name));
                else
                    s.(p.Name) = allprops.(p.Name);
                end
            end
        end
    else
        error(['Conversion to pure struct from ' class(thing) ' is not possible.']);
    end
end
function s = collapseObjects(s)
    fnames = fields(s);
    for i=1:length(fnames)
        f = s.(fnames{i});
        if isobject(f)
            s.(fnames{i}) = toPureStruct(f);
        elseif isstruct(f)
            s.(fnames{i}) = collapseObjects(f);
        end
    end
end
0 commentaires
Réponses (1)
  Ishaan
 le 21 Avr 2025
        
      Modifié(e) : Ishaan
 le 21 Avr 2025
  
      Hello, 
I understand that you are looking for a way to turn your struct back into a fully initialized object, even restoring private properties. 
We know that the base-class approach won’t simply work as MATLAB enforces private‑property access before run-time. But we can give set access to the base class from “Property Access List”. 
classdef XmlSerializable 
    methods 
        function obj = deserialize(obj, s) 
            % logic 
        end 
    end 
end 
classdef MyClass < XmlSerializable
    properties (SetAccess = ?XmlSerializable) 
        % Now only MyClass and XmlSerializable may read or write 
        privateProperty 
    end 
end
Now the following code will work 
obj = MyClass(); 
obj.deserialize(s); 
The serialization logic can be done in the following ways: 
1. for loop 
fn = fieldnames(s); 
for k = 1:numel(fn) 
    obj.(fn{k}) = s.(fn{k}); 
end 
Here, you iterate through the field names and assign the value to the corresponding object property. Since this assignment happens inside the class’s own method, it can legally access private properties. 
2. set method 
You can inherit your class form "matlab.mixin.SetGet" and perform deserialization in a single line. 
set(obj, ([fieldnames(s), struct2cell(s)]'){:}); 
This snippet converts the struct into name-value pairs using "fieldnames" and "struct2cell", and set assigns all the properties in one batch. Again, since the call happens inside the class’s namespace, private and protected access is respected. 
Additionally, you can extract the deserialization logic into a reusable helper method. However, the function call still needs to happen inside each user-created class separately. 
To use a helper function, define it in a file that is added to the MATLAB path. 
function obj = xmlDeserialize(obj, s) 
% some logic 
end 
Now, you can call this helper function in your class. 
If you do not want to explicitly update “Property Access List” and are okay with declaring serialization inside the class itself. You can do so in the constructor, a deserialize method, or a factory method. 
classdef MyClass 
    methods 
        function obj = MyClass(s) % constructor 
            if nargin > 0 
                obj = MyClass(); 
                obj = xmlDeserialize(obj, s); 
            end 
        end 
        function obj = load(obj, s) % class method 
            obj = MyClass(); 
            obj = xmlDeserialize(obj, s); 
        end 
    end 
    methods (Static) 
        function obj = fromStruct(s) % factory method 
            obj = MyClass(); 
            obj = xmlDeserialize(obj, s); 
        end 
    end 
end 
You can now deserialize the struct into your class, in the following ways. 
s = struct('privateProperty', 'Hello', 'publicProperty', 'World'); 
obj1 = MyClass(s); % constructor 
obj2 = MyClass(); 
obj2.load(s); % class method 
obj3 = MyClass.fromStruct(s); % factory method 
In summary 
Hope this helped. 
0 commentaires
Voir également
Catégories
				En savoir plus sur Java Package Integration dans Help Center et File Exchange
			
	Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

