Convert Lua object to JSON in Corona SDK - oop

I'm coming from more OO languages (Java, C++, C#), so it's a bit hard for me to wrap my head around how lua handles objects.
I have a user object declared as follows in a User.lua file:
local User = {align="neutral", justness=50, sceneData=nil};
I attempt to convert it to JSON to save in a text file like this in the User.lua file
function User:save ()
print ("Saving game state")
local data = json.encode(self);
local file = io.open (path, "w");
file:write ( data );
io.close( file );
file = nil;
end
The function call is:
User:save();
And the program just saves [] in the text file. How do I reference the object in such a way that it saves the table data? (Edit:) I would like to be able to save the table and make it so that I am able to create a new object with the data in the table after the user closes and reopens the app.
Additionally, sceneData is an object of class Scene, will that encode the table data for that Scene object, or will I need to fiddle with that as well?

Related

how can i save and return an object in/from json file?

i am working on coreldraw v2020 , writing macro and i need to save shape objects in JSON file .
is there any method to write the object directly in the file ?
the programming language is vusial basic

TypeScript API for SourceFile creation: how to get syntactic errors information

TypeScript API Program has method getSyntacticDiagnostics to get syntactic errors. But if there is no Program, just SourceFile how can I get the same kind of information?
I created SourceFile through
function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile;
Remember that fileName (string) parameter in createSourceFile is virtual file name. This fileName (string) is used globaly while using TypeScript library.
The most important thing what you need is what doc comment on createProgam method says. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' that represent a compilation unit. createProgam method as first parameter requires list of strings which are virtual names of files used in this program.
If you don't understand previous 2 theoretical paragraphs I think that comments in sample will help you.
// this is the real code of file. Use fs.readFile, fs.readFileSync or something other to load file real source code.
var code = "class 1X {}";
// I will use this virtual name to reference SourceFile while working with TypeScript API.
var virtualFileName = "aaa.ts";
// initialize SourceFile instance
var sf = ts.createSourceFile(virtualFileName, code, ts.ScriptTarget.ES5);
// Make program as collection of my one virtual file
var prog = ts.createProgram([virtualFileName], {});
// process response as you need.
console.log(prog.getSyntacticDiagnostics(sf));

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
EDIT: One of the other "applications" I would like to read the saved files is a version control system (to track changes in parameters in configurations defined by Matlab objects), so any viable solution must be capable of producing human-intelligible text. The toPureStruct method above does this when the struct is converted to XML.
You might be able to sidestep this issue by using the new v7.3 MAT file format for your saved objects. Unlike the older MAT file formats, v7.3 is a variant of the HDF5, and there's HDF5 support and libraries in other languages. This could be a lot less work, and you'd probably get better performance too, since HDF5 is going to have a more efficient representation of numeric arrays than naive XML will.
It's not the default format; you can enable it using the -v7.3 switch to the save function.
To the best of my knowledge, what I want to do is impossible in Matlab 2011b. It might be possible, per #Andrew Janke's answer, to do something similar using Matlab's load command on binary HDF5 files that can be read and modified by other programs. But, this adds an enormous amount of complexity as Matlab's HDF5 representation of even the simplest class is extremely opaque. For instance, if I create a SimpleClass classdef in Matlab with two standard properties (prop1 and prop2), the HDF5 binary generated with the -v7.3 switch is 7k, and the expanded XML is 21k, and the text "prop1" and "prop2" do not appear anywhere. What I really want to create from that SimpleClass is this:
<root>
<classname>SimpleClass</classname>
<prop1>123</prop1>
<prop2>456</prop2>
</root>
I do not think it is possible to produce the above text from class properties in a generalized fashion in Matlab, even though it would be possible, for instance, in .NET or Java.

MATLAB and the use of global variables?

I am writing a tool for dicom images and spectroscopy and there is a lot of shared data I want to use between the functions I am making. I have GUI that I made and the different sliders and buttons use a lot of this shared data from the dicom files.
I have been using global variables to store information that all of these functions share. I have a lot of globals currently. I have been taught to avoid global variables if possible because of increasing coupling. Would it be better to read in the data from the dicom file in each function? This seems redundant. Would using MATLAB as object-oriented help?
I would recommend using application data structures.
Application data is essential data stored as a structure that is defined by your application and is typically attached to a GUI application or figure window.
To use application data (appdata) use the setappdata and getappdata functions. For example, assuming that you have a handle to your GUI stored as hGUI, the following adds a random matrix to your application data and then retrieves it later (lifted from MATLAB documentation)
% Save matrix for later
matrix = randn(35);
setappdata(hGUI, 'mydata', matrix);
% Do some stuff...
% Retrieve my matrix, this could be in a different file to `setappdata`
myMatrix = getappdata(hGUI, 'mydata');
You can store essentially arbitrary data in your application data, and you can store it and get it from any of your source files, as long as hGUI refers to your GUI application.
Since you mention you are working with a GUI and wanting to share data between the control callbacks, I would suggest designing your code using nested functions. The overall code would look something like this:
function dicomGUI
%# Initialize your GUI here, linking the control callbacks to the
%# nested functions below:
hLoad = uicontrol('Style', 'push', 'String', 'Load file', ...
'Callback', #load_file);
...
%# Initialize the data variables for the DICOM files here:
data = []; %# Shared among nested functions
...
%# Below are all the nested functions your controls will use:
function load_file(hSource, event)
data = ...; %# Load the data here
end
...
end
Not only does this let you put all your GUI code in one m-file, but it simplifies the control callbacks and makes it easy for them to share variables in the workspace of the parent function dicomGUI. An example of this approach, along with other suggestions for sharing data between GUI controls, can be found on this documentation page: Share Data Among a GUI's Callbacks.
As Chris mentions, this could become a very large m-file for a large and intricate GUI. To keep the file size down in such a case I would suggest making the body of each callback simply a call to a function in a separate file which accepts the shared data variables, performs whatever work is necessary, then returns the modified data to the same shared variables. For example:
function transform_callback(hSource, event)
%# Apply some transform to the data:
data = transform_data(data);
%# If the above changes the GUI (disabling controls, changing a
%# display, etc.), then those changes should be made here.
end
Globals as a rule are a bad thing. There are a couple of better ways typically, which include:
Reading in the data initially, and passing it to each function which needs it.
Reading it the data, and each function which needs it calls a function which returns it.
You might need to update the data package upon return somehow as well, depending on if you only use the data or if you change the data as well as using it.
Either one of these ideas should help your process. It makes your code much more readable, and less likely to make some kind of a mistake.
There is another possibility due to the object-oriented nature of MATLAB. You can define your own handle class and pass it in the initialization phase to each callback as an additional argument:
classdef Data<handle
properties (Access=public)
Val;
end
end
function SimpleGui
data = Data();
hLoad = uicontrol('Style', 'push', 'String', 'Push me', ...
'Callback', {#callback data});
data.Val = 5;
end
function callback(hSource, event, data)
data.Val = data.Val+1;
disp(data.Val);
end
Yet another option:
Also, regarding the guidata/appdata (as described by #Chris), it can be improved in the following way:
Create an encapsulating callback that always gets and sets guidata:
function CallbackWrapper(hObj,evt,func)
data = guidata(hObj);
data = func(hObj,evt,data);
guidata(hObj,data);
end
Now your callbacks should be defined in the following way (note the different signature):
function SimpleGui
hSave = uicontrol('Style', 'push', 'String', 'Push me', ...
'Callback', {#CallbackWrapper #myCallBack});
data.x = 1;
guidata(hSave,data);
end
function data = myCallBack(hObj,evt,data)
data.x = data.x + 1;
disp(data.x);
end
If you are using one of the later releases of MATLAB, you should take advantage of the OOPS (object oriented programming system).
You should adhere to software design principles and start by architecting a sound software design. You should do this before writing any code. I recommend using UML for software modeling.

loading serialized data into a table

For an answer to another question, I wanted to load some serialized lua code into a table. The string to be loaded is of this form:
SavedVars = { }
SavedStats = { }
(where each of the {...} might be any Lua expression, including a table constructor with nested data. I'm assuming it is not calling any (global) functions or using global variables.
What I finally want to have is a table of this form:
{ ["SavedVar"] = { }, ["SavedStats"] = { } }
I do not want to have global variables SavedVars afterwards.
How to do this most elegantly?
(I already found a solution, but maybe someone has a better one.)
Here is my solution:
-- loads a string to a table.
-- this executes the string with the environment of a new table, and then
-- returns the table.
--
-- The code in the string should not need any variables it does not declare itself,
-- as these are not available on runtime. It runs in a really empty environment.
function loadTable(data)
local table = {}
local f = assert(loadstring(data))
setfenv(f, table)
f()
return table
end
It loads the data string with loadstring and then uses setfenv to modify the global environment of the function to a new table. Then calling the loaded function once fills this table (instead of the global environment), which we then can return.
Setting the environment to a new table has the effect that the code can't use any global data at all. I think this is a good way to sandbox the code, but if it is not wanted, you could populate the table before or provide it with some metatable (but unset it before returning the table).
This loading function will also work with serialized data produced like in Saving Tables with Cycles.