Hello Daniel Thank you for your improved JSON creator for Octave.
While it has already been included in the octave-forge io package last spring (1.0.14) I had no time to have a good look at it; Soren has just put it in the io package w/o looking back (no problem there BTW).
As io package maintainer and self-assigned QA dude for that package I took the liberty to adapt your object2json.m file to some layout standards that apply (should apply) to all code in at least OF's main branch.
There are various reasons for that; readability, maintanability, ... I left some standards aside (# rather than % comment line etc). Some questions: - Do you agree with the changes I made? (see attached file) Please note: I have no idea what object2json.m is supposed to do. - Can you add some usage descriptor in the header, so if someone types help object2json he/she gets an idea of how to invoke the object2json.m file?- Could you make up some test cases to show how the file works and to verify that it gives correct output?
Thanks, Philip
%% Copyright (C) 2010 Torre Herrera, Daniel de %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; either version 2 of the License, or %% (at your option) any later version. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with Octave; see the file COPYING. If not, see %% <http://www.gnu.org/licenses/>. %% object2json.m %% Created: 2010-12-06 %% Updates: %% 2011-01-23 Added support for especial chars and escaped sequences %% 2011-04-01 Fixed error: Column vectors not working correctly %% 2011-09-08 (Philip Nienhuis) layout & style changes cf. Octave coding style function json = object2json (object) % function json = object2json (object) % This function returns a valid json string that will describe object % The string will be in a compact form (i.e. no spaces or line breaks) % % It will map simple octave values this way: % function handles: string with the name of the function % double (numbers): depends: % If it's real it will map to a string representing that number % If it's complex it will map to an object with the next properties: % real: real part of the number % imag: imaginary part of the number % char: A string enclosed by double quotes representing that character % And will map more complex octave values this other way: % struct: an object with properties equal to the struct's field names % and value equal to the json counterpart of that field % cell: it will be mapped depending on the value of the cell (for % example {i} will be mapped to an object with real=0 and imag=1) % vectors or cell arrays: it will map them to a corresponding js % array (same size) with the values transformed to their json % counterpart (Note: that in javascript all arrays are like octave's % cells ,i.e. they can store different type and size variables) % strings or char vectors: they will be mapped to the same string % enclosed by double quotes % Other octave values will be mapped to a string enclosed by double % quotes with the value that the class() function returns % It can handle escape sequences and special chars automatically. % If they're valid in JSON it will keep them if not they'll be % escaped so they can become valid s = size (object); if (all (s==1)) % It's not a vector so we must check how to map it % Depending on the class of the object we must do one or another thing switch (class (object)) case 'function_handle' % For a function handle we will only print the name fun = functions (object); json = [ '"', fun.function, '"' ]; case 'struct' fields = fieldnames (object); results = cellfun (@object2json, struct2cell (object), "UniformOutput", false); json = '{'; if (numel (fields) > 1) sep = ','; else sep = ''; endif for (tmp = 1:numel (fields)) json = [ json, '"', fields{tmp}, '":', results{tmp}, sep ]; if(tmp >= numel (fields)-1) sep = ''; endif endfor json(end+1) = '}'; case 'cell' % We dereference the cell and use it as a new value json = object2json (object{1}); case 'double' if (isreal (object)) json = num2str (object); else if (iscomplex (object)) json = [ '{"real":', num2str(real(object)), ',"imag":' , num2str(imag(object)), '}' ]; endif endif case 'char' % Here we handle a single char % JSON only admits the next escape sequences: % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits % so we must be sure that every other sequence gets replaced object = replace_non_JSON_escapes (object); json = [ '"', object, '"' ]; otherwise % We don't know what is it so we'll put the class name json = [ '"', class(object), '"' ]; endswitch else % It's a vector so it maps to an array sep = ''; if (numel (s) > 2) json = '['; for (tmp=1:s(1)) json = [ json, sep, object2json(reshape(object(tmp, :), s(2:end))) ]; sep = ','; endfor json(end+1) = ']'; else % We can have three cases here: % Object is a row -> array with all the elements % Object is a column -> each element is an array in it's own % Object is a 2D matrix -> separate each row if (s(1) == 1) % Object is a row if (ischar (object)) % If it's a row of chars we will take it as a string % JSON only admits the next escape sequences: % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits % so we must be sure that every other sequence gets replaced object = replace_non_JSON_escapes (object); json = [ '"', object, '"']; else json = '['; for (tmp=1:s(2)) json = [ json, sep, object2json(object(1, tmp)) ]; sep = ','; endfor json(end+1) = ']'; endif elseif (s(2) == 1) % Object is a column json = '['; for (tmp=1:s(1)) json = [ json, sep, '[', object2json(object(tmp, 1)), ']' ]; sep = ','; endfor json(end+1) = ']'; else % Object is a 2D matrix json = '['; for (tmp=1:s(1)) json = [ json, sep, object2json(object(tmp, :)) ]; sep = ','; endfor json(end+1) = ']'; endif endif endif endfunction % JSON only admits the next escape sequences: % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits % This function replace every escaped sequence that isn't on that list % with a compatible version % Note that this function uses typeinfo so it may need to be updated % with each octave release function object = replace_non_JSON_escapes (object) if (strcmp (typeinfo (object), 'string')) % It's a double quoted string so newlines and other chars need % to be converted back into escape sequences before anything object = undo_string_escapes (object); endif % This first regex handles double quotes and slashes that are not % after a backslash and thus aren't escaped object = regexprep (object, '(?<!\\)(["/])', "\\$1"); % This regex handle double quotes and slashes that are after an even % number of backslashes and thus aren't escaped object = regexprep (object, '(?<!\\)(\\\\)*(["/])', "$1\\$2"); % This last one regexp handle any other valid JSON escape sequence object = regexprep (object, '(?<!\\)\\(?=(\\\\)*(?!([\"\\\/bfnrt]|([u][0-9A-Fa-f]{4}))+?))', "\\\\"); endfunction
------------------------------------------------------------------------------ All the data continuously generated in your IT infrastructure contains a definitive record of customers, application performance, security threats, fraudulent activity and more. Splunk takes this data and makes sense of it. Business sense. IT sense. Common sense. http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________ Octave-dev mailing list Octave-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/octave-dev