- 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?
5 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
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 comentarios
Respuestas (1)
Ishaan
el 21 de Abr. de 2025
Editada: Ishaan
el 21 de Abr. de 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 comentarios
Ver también
Categorías
Más información sobre Java Package Integration en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!