1 %% Copyright (C) 2010 Torre Herrera, Daniel de
3 %% This program is free software; you can redistribute it and/or modify it under
4 %% the terms of the GNU General Public License as published by the Free Software
5 %% Foundation; either version 3 of the License, or (at your option) any later
8 %% This program is distributed in the hope that it will be useful, but WITHOUT
9 %% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 %% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 %% You should have received a copy of the GNU General Public License along with
14 %% this program; if not, see <http://www.gnu.org/licenses/>.
16 %% Returns a valid json string that will describe object; the string will
17 %% be in a compact form (no spaces or line breaks).
19 %% It will map simple octave values this way:
20 %% function handles: string with the name of the function
21 %% double (numbers): depends:
22 %% If it's real it will map to a string representing that number
23 %% If it's complex it will map to an object with the next properties:
24 %% real: real part of the number
25 %% imag: imaginary part of the number
26 %% char: A string enclosed by double quotes representing that character
27 %% And will map more complex octave values this other way:
28 %% struct: an object with properties equal to the struct's field names
29 %% and value equal to the json counterpart of that field
30 %% cell: it will be mapped depending on the value of the cell (for
31 %% example {i} will be mapped to an object with real=0 and imag=1)
32 %% vectors or cell arrays: it will map them to a corresponding js
33 %% array (same size) with the values transformed to their json
34 %% counterpart (Note: that in javascript all arrays are like octave's
35 %% cells ,i.e. they can store different type and size variables)
36 %% strings or char vectors: they will be mapped to the same string
37 %% enclosed by double quotes
38 %% Other octave values will be mapped to a string enclosed by double
39 %% quotes with the value that the class() function returns
40 %% It can handle escape sequences and special chars automatically.
41 %% If they're valid in JSON it will keep them if not they'll be
42 %% escaped so they can become valid
45 %% Created: 2010-12-06
47 %% 2011-01-23 Added support for especial chars and escaped sequences
48 %% 2011-04-01 Fixed error: Column vectors not working correctly
49 %% 2011-09-08 (Philip Nienhuis) layout & style changes cf. Octave coding style
51 function json = object2json (object)
55 % It's not a vector so we must check how to map it
56 % Depending on the class of the object we must do one or another thing
57 switch (class (object))
58 case 'function_handle'
59 % For a function handle we will only print the name
60 fun = functions (object);
61 json = [ '"', fun.function, '"' ];
64 fields = fieldnames (object);
65 results = cellfun (@object2json, struct2cell (object), "UniformOutput", false);
67 if (numel (fields) > 1)
72 for (tmp = 1:numel (fields))
73 json = [ json, '"', fields{tmp}, '":', results{tmp}, sep ];
74 if(tmp >= numel (fields)-1)
81 % We dereference the cell and use it as a new value
82 json = object2json (object{1});
86 json = num2str (object);
88 if (iscomplex (object))
89 json = [ '{"real":', num2str(real(object)), ',"imag":' , num2str(imag(object)), '}' ];
94 % Here we handle a single char
95 % JSON only admits the next escape sequences:
96 % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits
97 % so we must be sure that every other sequence gets replaced
98 object = replace_non_JSON_escapes (object);
99 json = [ '"', object, '"' ];
102 % We don't know what is it so we'll put the class name
103 json = [ '"', class(object), '"' ];
107 % It's a vector so it maps to an array
112 json = [ json, sep, object2json(reshape(object(tmp, :), s(2:end))) ];
118 % We can have three cases here:
119 % Object is a row -> array with all the elements
120 % Object is a column -> each element is an array in it's own
121 % Object is a 2D matrix -> separate each row
125 % If it's a row of chars we will take it as a string
126 % JSON only admits the next escape sequences:
127 % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits
128 % so we must be sure that every other sequence gets replaced
129 object = replace_non_JSON_escapes (object);
130 json = [ '"', object, '"'];
135 json = [ json, sep, object2json(object(1, tmp)) ];
145 json = [ json, sep, '[', object2json(object(tmp, 1)), ']' ];
151 % Object is a 2D matrix
154 json = [ json, sep, object2json(object(tmp, :)) ];
166 % JSON only admits the next escape sequences:
167 % \", \\, \/, \b, \f, \n, \r, \t and \u four-hex-digits
168 % This function replace every escaped sequence that isn't on that list
169 % with a compatible version
170 % Note that this function uses typeinfo so it may need to be updated
171 % with each octave release
173 function object = replace_non_JSON_escapes (object)
175 if (strcmp (typeinfo (object), 'string'))
176 % It's a double quoted string so newlines and other chars need
177 % to be converted back into escape sequences before anything
178 object = undo_string_escapes (object);
180 % This first regex handles double quotes and slashes that are not
181 % after a backslash and thus aren't escaped
182 object = regexprep (object, '(?<!\\)(["/])', "\\$1");
183 % This regex handle double quotes and slashes that are after an even
184 % number of backslashes and thus aren't escaped
185 object = regexprep (object, '(?<!\\)(\\\\)*(["/])', "$1\\$2");
186 % This last one regexp handle any other valid JSON escape sequence
187 object = regexprep (object, '(?<!\\)\\(?=(\\\\)*(?!([\"\\\/bfnrt]|([u][0-9A-Fa-f]{4}))+?))', "\\\\");