Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/Coursera-Machine-Learning
Path: blob/master/Week 9/Programming Assignment - 8/ex8/lib/jsonlab/savejson.m
626 views
1
function json=savejson(rootname,obj,varargin)
2
%
3
% json=savejson(rootname,obj,filename)
4
% or
5
% json=savejson(rootname,obj,opt)
6
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...)
7
%
8
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
9
% Object Notation) string
10
%
11
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
12
% created on 2011/09/09
13
%
14
% $Id: savejson.m 460 2015-01-03 00:30:45Z fangq $
15
%
16
% input:
17
% rootname: the name of the root-object, when set to '', the root name
18
% is ignored, however, when opt.ForceRootName is set to 1 (see below),
19
% the MATLAB variable name will be used as the root name.
20
% obj: a MATLAB object (array, cell, cell array, struct, struct array).
21
% filename: a string for the file name to save the output JSON data.
22
% opt: a struct for additional options, ignore to use default values.
23
% opt can have the following fields (first in [.|.] is the default)
24
%
25
% opt.FileName [''|string]: a file name to save the output JSON data
26
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element
27
% of a 1D/2D array;
28
% opt.ArrayIndent [1|0]: if 1, output explicit data array with
29
% precedent indentation; if 0, no indentation
30
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
31
% array in JSON array format; if sets to 1, an
32
% array will be shown as a struct with fields
33
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
34
% sparse arrays, the non-zero elements will be
35
% saved to _ArrayData_ field in triplet-format i.e.
36
% (ix,iy,val) and "_ArrayIsSparse_" will be added
37
% with a value of 1; for a complex array, the
38
% _ArrayData_ array will include two columns
39
% (4 for sparse) to record the real and imaginary
40
% parts, and also "_ArrayIsComplex_":1 is added.
41
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem
42
% will use true/false rather than 1/0.
43
% opt.NoRowBracket [1|0]: if this is set to 1, arrays with a single
44
% numerical element will be shown without a square
45
% bracket, unless it is the root object; if 0, square
46
% brackets are forced for any numerical arrays.
47
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson
48
% will use the name of the passed obj variable as the
49
% root object name; if obj is an expression and
50
% does not have a name, 'root' will be used; if this
51
% is set to 0 and rootname is empty, the root level
52
% will be merged down to the lower level.
53
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern
54
% to represent +/-Inf. The matched pattern is '([-+]*)Inf'
55
% and $1 represents the sign. For those who want to use
56
% 1e999 to represent Inf, they can set opt.Inf to '$11e999'
57
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern
58
% to represent NaN
59
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
60
% for example, if opt.JSONP='foo', the JSON data is
61
% wrapped inside a function call as 'foo(...);'
62
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
63
% back to the string form
64
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode.
65
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs)
66
%
67
% opt can be replaced by a list of ('param',value) pairs. The param
68
% string is equivallent to a field in opt and is case sensitive.
69
% output:
70
% json: a string in the JSON format (see http://json.org)
71
%
72
% examples:
73
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
74
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
75
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
76
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
77
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',...
78
% 'SpecialData',[nan, inf, -inf]);
79
% savejson('jmesh',jsonmesh)
80
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g')
81
%
82
% license:
83
% BSD, see LICENSE_BSD.txt files for details
84
%
85
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
86
%
87
88
if(nargin==1)
89
varname=inputname(1);
90
obj=rootname;
91
if(isempty(varname))
92
varname='root';
93
end
94
rootname=varname;
95
else
96
varname=inputname(2);
97
end
98
if(length(varargin)==1 && ischar(varargin{1}))
99
opt=struct('FileName',varargin{1});
100
else
101
opt=varargin2struct(varargin{:});
102
end
103
opt.IsOctave=exist('OCTAVE_VERSION','builtin');
104
rootisarray=0;
105
rootlevel=1;
106
forceroot=jsonopt('ForceRootName',0,opt);
107
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot==0)
108
rootisarray=1;
109
rootlevel=0;
110
else
111
if(isempty(rootname))
112
rootname=varname;
113
end
114
end
115
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot)
116
rootname='root';
117
end
118
119
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
120
if(jsonopt('Compact',0,opt)==1)
121
whitespaces=struct('tab','','newline','','sep',',');
122
end
123
if(~isfield(opt,'whitespaces_'))
124
opt.whitespaces_=whitespaces;
125
end
126
127
nl=whitespaces.newline;
128
129
json=obj2json(rootname,obj,rootlevel,opt);
130
if(rootisarray)
131
json=sprintf('%s%s',json,nl);
132
else
133
json=sprintf('{%s%s%s}\n',nl,json,nl);
134
end
135
136
jsonp=jsonopt('JSONP','',opt);
137
if(~isempty(jsonp))
138
json=sprintf('%s(%s);%s',jsonp,json,nl);
139
end
140
141
% save to a file if FileName is set, suggested by Patrick Rapin
142
if(~isempty(jsonopt('FileName','',opt)))
143
if(jsonopt('SaveBinary',0,opt)==1)
144
fid = fopen(opt.FileName, 'wb');
145
fwrite(fid,json);
146
else
147
fid = fopen(opt.FileName, 'wt');
148
fwrite(fid,json,'char');
149
end
150
fclose(fid);
151
end
152
153
%%-------------------------------------------------------------------------
154
function txt=obj2json(name,item,level,varargin)
155
156
if(iscell(item))
157
txt=cell2json(name,item,level,varargin{:});
158
elseif(isstruct(item))
159
txt=struct2json(name,item,level,varargin{:});
160
elseif(ischar(item))
161
txt=str2json(name,item,level,varargin{:});
162
else
163
txt=mat2json(name,item,level,varargin{:});
164
end
165
166
%%-------------------------------------------------------------------------
167
function txt=cell2json(name,item,level,varargin)
168
txt='';
169
if(~iscell(item))
170
error('input is not a cell');
171
end
172
173
dim=size(item);
174
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
175
item=reshape(item,dim(1),numel(item)/dim(1));
176
dim=size(item);
177
end
178
len=numel(item);
179
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:});
180
padding0=repmat(ws.tab,1,level);
181
padding2=repmat(ws.tab,1,level+1);
182
nl=ws.newline;
183
if(len>1)
184
if(~isempty(name))
185
txt=sprintf('%s"%s": [%s',padding0, checkname(name,varargin{:}),nl); name='';
186
else
187
txt=sprintf('%s[%s',padding0,nl);
188
end
189
elseif(len==0)
190
if(~isempty(name))
191
txt=sprintf('%s"%s": []',padding0, checkname(name,varargin{:})); name='';
192
else
193
txt=sprintf('%s[]',padding0);
194
end
195
end
196
for j=1:dim(2)
197
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end
198
for i=1:dim(1)
199
txt=sprintf('%s%s',txt,obj2json(name,item{i,j},level+(dim(1)>1)+1,varargin{:}));
200
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
201
end
202
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end
203
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
204
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
205
end
206
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end
207
208
%%-------------------------------------------------------------------------
209
function txt=struct2json(name,item,level,varargin)
210
txt='';
211
if(~isstruct(item))
212
error('input is not a struct');
213
end
214
dim=size(item);
215
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
216
item=reshape(item,dim(1),numel(item)/dim(1));
217
dim=size(item);
218
end
219
len=numel(item);
220
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'));
221
ws=jsonopt('whitespaces_',ws,varargin{:});
222
padding0=repmat(ws.tab,1,level);
223
padding2=repmat(ws.tab,1,level+1);
224
padding1=repmat(ws.tab,1,level+(dim(1)>1)+(len>1));
225
nl=ws.newline;
226
227
if(~isempty(name))
228
if(len>1) txt=sprintf('%s"%s": [%s',padding0,checkname(name,varargin{:}),nl); end
229
else
230
if(len>1) txt=sprintf('%s[%s',padding0,nl); end
231
end
232
for j=1:dim(2)
233
if(dim(1)>1) txt=sprintf('%s%s[%s',txt,padding2,nl); end
234
for i=1:dim(1)
235
names = fieldnames(item(i,j));
236
if(~isempty(name) && len==1)
237
txt=sprintf('%s%s"%s": {%s',txt,padding1, checkname(name,varargin{:}),nl);
238
else
239
txt=sprintf('%s%s{%s',txt,padding1,nl);
240
end
241
if(~isempty(names))
242
for e=1:length(names)
243
txt=sprintf('%s%s',txt,obj2json(names{e},getfield(item(i,j),...
244
names{e}),level+(dim(1)>1)+1+(len>1),varargin{:}));
245
if(e<length(names)) txt=sprintf('%s%s',txt,','); end
246
txt=sprintf('%s%s',txt,nl);
247
end
248
end
249
txt=sprintf('%s%s}',txt,padding1);
250
if(i<dim(1)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
251
end
252
if(dim(1)>1) txt=sprintf('%s%s%s]',txt,nl,padding2); end
253
if(j<dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
254
end
255
if(len>1) txt=sprintf('%s%s%s]',txt,nl,padding0); end
256
257
%%-------------------------------------------------------------------------
258
function txt=str2json(name,item,level,varargin)
259
txt='';
260
if(~ischar(item))
261
error('input is not a string');
262
end
263
item=reshape(item, max(size(item),[1 0]));
264
len=size(item,1);
265
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
266
ws=jsonopt('whitespaces_',ws,varargin{:});
267
padding1=repmat(ws.tab,1,level);
268
padding0=repmat(ws.tab,1,level+1);
269
nl=ws.newline;
270
sep=ws.sep;
271
272
if(~isempty(name))
273
if(len>1) txt=sprintf('%s"%s": [%s',padding1,checkname(name,varargin{:}),nl); end
274
else
275
if(len>1) txt=sprintf('%s[%s',padding1,nl); end
276
end
277
isoct=jsonopt('IsOctave',0,varargin{:});
278
for e=1:len
279
if(isoct)
280
val=regexprep(item(e,:),'\\','\\');
281
val=regexprep(val,'"','\"');
282
val=regexprep(val,'^"','\"');
283
else
284
val=regexprep(item(e,:),'\\','\\\\');
285
val=regexprep(val,'"','\\"');
286
val=regexprep(val,'^"','\\"');
287
end
288
val=escapejsonstring(val);
289
if(len==1)
290
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"'];
291
if(isempty(name)) obj=['"',val,'"']; end
292
txt=sprintf('%s%s%s%s',txt,padding1,obj);
293
else
294
txt=sprintf('%s%s%s%s',txt,padding0,['"',val,'"']);
295
end
296
if(e==len) sep=''; end
297
txt=sprintf('%s%s',txt,sep);
298
end
299
if(len>1) txt=sprintf('%s%s%s%s',txt,nl,padding1,']'); end
300
301
%%-------------------------------------------------------------------------
302
function txt=mat2json(name,item,level,varargin)
303
if(~isnumeric(item) && ~islogical(item))
304
error('input is not an array');
305
end
306
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
307
ws=jsonopt('whitespaces_',ws,varargin{:});
308
padding1=repmat(ws.tab,1,level);
309
padding0=repmat(ws.tab,1,level+1);
310
nl=ws.newline;
311
sep=ws.sep;
312
313
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ...
314
isempty(item) ||jsonopt('ArrayToStruct',0,varargin{:}))
315
if(isempty(name))
316
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
317
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
318
else
319
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
320
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
321
end
322
else
323
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1 && level>0)
324
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']','');
325
else
326
numtxt=matdata2json(item,level+1,varargin{:});
327
end
328
if(isempty(name))
329
txt=sprintf('%s%s',padding1,numtxt);
330
else
331
if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1)
332
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
333
else
334
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
335
end
336
end
337
return;
338
end
339
dataformat='%s%s%s%s%s';
340
341
if(issparse(item))
342
[ix,iy]=find(item);
343
data=full(item(find(item)));
344
if(~isreal(item))
345
data=[real(data(:)),imag(data(:))];
346
if(size(item,1)==1)
347
% Kludge to have data's 'transposedness' match item's.
348
% (Necessary for complex row vector handling below.)
349
data=data';
350
end
351
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
352
end
353
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep);
354
if(size(item,1)==1)
355
% Row vector, store only column indices.
356
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
357
matdata2json([iy(:),data'],level+2,varargin{:}), nl);
358
elseif(size(item,2)==1)
359
% Column vector, store only row indices.
360
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
361
matdata2json([ix,data],level+2,varargin{:}), nl);
362
else
363
% General case, store row and column indices.
364
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
365
matdata2json([ix,iy,data],level+2,varargin{:}), nl);
366
end
367
else
368
if(isreal(item))
369
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
370
matdata2json(item(:)',level+2,varargin{:}), nl);
371
else
372
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
373
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
374
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl);
375
end
376
end
377
txt=sprintf('%s%s%s',txt,padding1,'}');
378
379
%%-------------------------------------------------------------------------
380
function txt=matdata2json(mat,level,varargin)
381
382
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
383
ws=jsonopt('whitespaces_',ws,varargin{:});
384
tab=ws.tab;
385
nl=ws.newline;
386
387
if(size(mat,1)==1)
388
pre='';
389
post='';
390
level=level-1;
391
else
392
pre=sprintf('[%s',nl);
393
post=sprintf('%s%s]',nl,repmat(tab,1,level-1));
394
end
395
396
if(isempty(mat))
397
txt='null';
398
return;
399
end
400
floatformat=jsonopt('FloatFormat','%.10g',varargin{:});
401
%if(numel(mat)>1)
402
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]];
403
%else
404
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]];
405
%end
406
407
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1)
408
formatstr=[repmat(tab,1,level) formatstr];
409
end
410
411
txt=sprintf(formatstr,mat');
412
txt(end-length(nl):end)=[];
413
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1)
414
txt=regexprep(txt,'1','true');
415
txt=regexprep(txt,'0','false');
416
end
417
%txt=regexprep(mat2str(mat),'\s+',',');
418
%txt=regexprep(txt,';',sprintf('],\n['));
419
% if(nargin>=2 && size(mat,1)>1)
420
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']);
421
% end
422
txt=[pre txt post];
423
if(any(isinf(mat(:))))
424
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:}));
425
end
426
if(any(isnan(mat(:))))
427
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:}));
428
end
429
430
%%-------------------------------------------------------------------------
431
function newname=checkname(name,varargin)
432
isunpack=jsonopt('UnpackHex',1,varargin{:});
433
newname=name;
434
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once')))
435
return
436
end
437
if(isunpack)
438
isoct=jsonopt('IsOctave',0,varargin{:});
439
if(~isoct)
440
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}');
441
else
442
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start');
443
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end');
444
if(isempty(pos)) return; end
445
str0=name;
446
pos0=[0 pend(:)' length(name)];
447
newname='';
448
for i=1:length(pos)
449
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))];
450
end
451
if(pos(end)~=length(name))
452
newname=[newname str0(pos0(end-1)+1:pos0(end))];
453
end
454
end
455
end
456
457
%%-------------------------------------------------------------------------
458
function newstr=escapejsonstring(str)
459
newstr=str;
460
isoct=exist('OCTAVE_VERSION','builtin');
461
if(isoct)
462
vv=sscanf(OCTAVE_VERSION,'%f');
463
if(vv(1)>=3.8) isoct=0; end
464
end
465
if(isoct)
466
escapechars={'\a','\f','\n','\r','\t','\v'};
467
for i=1:length(escapechars);
468
newstr=regexprep(newstr,escapechars{i},escapechars{i});
469
end
470
else
471
escapechars={'\a','\b','\f','\n','\r','\t','\v'};
472
for i=1:length(escapechars);
473
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\'));
474
end
475
end
476
477