Skip to content

Commit d07f788

Browse files
committed
[feat] user defined quote, array and object markers
1 parent 1b440af commit d07f788

File tree

1 file changed

+51
-39
lines changed

1 file changed

+51
-39
lines changed

savejson.m

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@
108108
% jsonencode, if presents (MATLAB R2016b or Octave
109109
% 6) first. If jsonencode does not exist or failed,
110110
% this function falls back to the jsonlab savejson
111+
% Whitespaces_: a struct customizing delimiters, including
112+
% tab: sprintf('\t') indentation
113+
% newline: sprintf('\n') newline between items
114+
% sep: ',' delim. between items
115+
% quote: '"' quotes for obj name
116+
% array: '[]' start/end of array
117+
% obj: '{}' start/end of object
118+
% for example, when printing a compact JSON string,
119+
% the savejson function internally use
120+
% struct('tab', '', 'newline', '', 'sep', ',')
111121
%
112122
% opt can be replaced by a list of ('param',value) pairs. The param
113123
% string is equivalent to a field in opt and is case sensitive.
@@ -228,12 +238,14 @@
228238
rootname = 'root';
229239
end
230240

231-
whitespaces = struct('tab', sprintf('\t'), 'newline', sprintf('\n'), 'sep', sprintf(',\n'));
241+
whitespaces = struct('tab', sprintf('\t'), 'newline', sprintf('\n'), 'sep', sprintf(',\n'), 'quote', '"', 'array', '[]', 'obj', '{}');
232242
if (opt.compact == 1)
233-
whitespaces = struct('tab', '', 'newline', '', 'sep', ',');
243+
whitespaces = struct('tab', '', 'newline', '', 'sep', ',', 'quote', '"', 'array', '[]', 'obj', '{}');
234244
end
235245
if (~isfield(opt, 'whitespaces_'))
236246
opt.whitespaces_ = whitespaces;
247+
else
248+
opt.whitespaces_ = mergestruct(whitespaces, opt.whitespaces_);
237249
end
238250

239251
nl = whitespaces.newline;
@@ -342,17 +354,17 @@
342354
bracketlevel = ~varargin{1}.singletcell;
343355
if (len > bracketlevel)
344356
if (~isempty(name))
345-
txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl};
357+
txt = {padding0, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote, ':', ws.array(1), nl};
346358
name = '';
347359
else
348-
txt = {padding0, '[', nl};
360+
txt = {padding0, ws.array(1), nl};
349361
end
350362
elseif (len == 0)
351363
if (~isempty(name))
352-
txt = {padding0, '"' decodevarname(name, varargin{1}.unpackhex) '":[]'};
364+
txt = {padding0, ws.quote decodevarname(name, varargin{1}.unpackhex) ws.quote ':' ws.array};
353365
name = '';
354366
else
355-
txt = {padding0, '[]'};
367+
txt = {padding0, ws.array};
356368
end
357369
txt = sprintf('%s', txt{:});
358370
return
@@ -365,7 +377,7 @@
365377
txt = [txt{:}, cellfun(@(x, id) [obj2json(name, x, level + (dim(1) > 1) + (len > bracketlevel), varargin{:}), sep{(id == length(item)) + 1}], item, idx, 'UniformOutput', false)];
366378

367379
if (len > bracketlevel)
368-
txt(end + 1:end + 3) = {nl, padding0, ']'};
380+
txt(end + 1:end + 3) = {nl, padding0, ws.array(2)};
369381
end
370382
txt = sprintf('%s', txt{:});
371383

@@ -393,32 +405,32 @@
393405

394406
if (isempty(item))
395407
if (~isempty(name))
396-
txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[]'};
408+
txt = {padding0, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote, ':', ws.array};
397409
else
398-
txt = {padding0, '[]'};
410+
txt = {padding0, ws.array};
399411
end
400412
txt = sprintf('%s', txt{:});
401413
return
402414
end
403415
if (~isempty(name))
404416
if (forcearray)
405-
txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl};
417+
txt = {padding0, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote ':', ws.array(1), nl};
406418
end
407419
else
408420
if (forcearray)
409-
txt = {padding0, '[', nl};
421+
txt = {padding0, ws.array(1), nl};
410422
end
411423
end
412424
for j = 1:dim(2)
413425
if (dim(1) > 1)
414-
txt(end + 1:end + 3) = {padding2, '[', nl};
426+
txt(end + 1:end + 3) = {padding2, ws.array(1), nl};
415427
end
416428
for i = 1:dim(1)
417429
names = fieldnames(item(i, j));
418430
if (~isempty(name) && len == 1 && ~forcearray)
419-
txt(end + 1:end + 5) = {padding1, '"', decodevarname(name, varargin{1}.unpackhex), '":{', nl};
431+
txt(end + 1:end + 7) = {padding1, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote, ':', ws.obj(1), nl};
420432
else
421-
txt(end + 1:end + 3) = {padding1, '{', nl};
433+
txt(end + 1:end + 3) = {padding1, ws.obj(1), nl};
422434
end
423435
if (~isempty(names))
424436
for e = 1:length(names)
@@ -436,20 +448,20 @@
436448
txt{end + 1} = nl;
437449
end
438450
end
439-
txt(end + 1:end + 2) = {padding1, '}'};
451+
txt(end + 1:end + 2) = {padding1, ws.obj(2)};
440452
if (i < dim(1))
441453
txt(end + 1:end + 2) = {',' nl};
442454
end
443455
end
444456
if (dim(1) > 1)
445-
txt(end + 1:end + 3) = {nl, padding2, ']'};
457+
txt(end + 1:end + 3) = {nl, padding2, ws.array(2)};
446458
end
447459
if (j < dim(2))
448460
txt(end + 1:end + 2) = {',' nl};
449461
end
450462
end
451463
if (forcearray)
452-
txt(end + 1:end + 3) = {nl, padding0, ']'};
464+
txt(end + 1:end + 3) = {nl, padding0, ws.array(2)};
453465
end
454466
txt = sprintf('%s', txt{:});
455467

@@ -502,17 +514,17 @@
502514

503515
if (isempty(item))
504516
if (~isempty(name))
505-
txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":[]'};
517+
txt = {padding0, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote, ':', ws.array};
506518
else
507-
txt = {padding0, '[]'};
519+
txt = {padding0, ws.array};
508520
end
509521
txt = sprintf('%s', txt{:});
510522
return
511523
end
512524
if (~isempty(name))
513-
txt = {padding0, '"', decodevarname(name, varargin{1}.unpackhex), '":{', nl};
525+
txt = {padding0, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote, ':', ws.obj(1), nl};
514526
else
515-
txt = {padding0, '{', nl};
527+
txt = {padding0, ws.obj(1), nl};
516528
end
517529

518530
for i = 1:dim(1)
@@ -528,7 +540,7 @@
528540
txt{end + 1} = nl;
529541
end
530542
end
531-
txt(end + 1:end + 3) = {nl, padding0, '}'};
543+
txt(end + 1:end + 3) = {nl, padding0, ws.obj(2)};
532544
txt = sprintf('%s', txt{:});
533545

534546
%% -------------------------------------------------------------------------
@@ -547,11 +559,11 @@
547559

548560
if (~isempty(name))
549561
if (len > 1)
550-
txt = {padding1, '"', decodevarname(name, varargin{1}.unpackhex), '":[', nl};
562+
txt = {padding1, ws.quote, decodevarname(name, varargin{1}.unpackhex), ws.quote ':', ws.array(1), nl};
551563
end
552564
else
553565
if (len > 1)
554-
txt = {padding1, '[', nl};
566+
txt = {padding1, ws.array(1), nl};
555567
end
556568
end
557569
for e = 1:len
@@ -561,21 +573,21 @@
561573
val = item(e, :);
562574
end
563575
if (len == 1)
564-
obj = ['"' decodevarname(name, varargin{1}.unpackhex) '":' '"', val, '"'];
576+
obj = [ws.quote decodevarname(name, varargin{1}.unpackhex) ws.quote ':' ws.quote, val, ws.quote];
565577
if (isempty(name))
566-
obj = ['"', val, '"'];
578+
obj = [ws.quote, val, ws.quote];
567579
end
568580
txt(end + 1:end + 2) = {padding1, obj};
569581
else
570-
txt(end + 1:end + 4) = {padding0, '"', val, '"'};
582+
txt(end + 1:end + 4) = {padding0, ws.quote, val, ws.quote};
571583
end
572584
if (e == len)
573585
sep = '';
574586
end
575587
txt{end + 1} = sep;
576588
end
577589
if (len > 1)
578-
txt(end + 1:end + 3) = {nl, padding1, ']'};
590+
txt(end + 1:end + 3) = {nl, padding1, ws.array(2)};
579591
end
580592
txt = sprintf('%s', txt{:});
581593

@@ -623,9 +635,9 @@
623635
txt = sprintf('%s%s', padding1, numtxt);
624636
else
625637
if (numel(item) == 1 && varargin{1}.singletarray == 0)
626-
txt = sprintf('%s"%s":%s', padding1, decodevarname(name, opt.unpackhex), numtxt);
638+
txt = sprintf('%s%s%s%s:%s', padding1, ws.quote, decodevarname(name, opt.unpackhex), ws.quote, numtxt);
627639
else
628-
txt = sprintf('%s"%s":%s', padding1, decodevarname(name, opt.unpackhex), numtxt);
640+
txt = sprintf('%s%s%s%s:%s', padding1, ws.quote, decodevarname(name, opt.unpackhex), ws.quote, numtxt);
629641
end
630642
end
631643
return
@@ -658,9 +670,9 @@
658670
fulldata = [ix, iy, data];
659671
end
660672
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipSize_":', regexprep(mat2str(size(fulldata)), '\s+', ','), sep);
661-
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, ['"' sep]);
673+
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, [ws.quote sep]);
662674
compfun = str2func([dozip 'encode']);
663-
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', base64encode(compfun(typecast(fulldata(:), 'uint8'))), ['"' nl]);
675+
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', base64encode(compfun(typecast(fulldata(:), 'uint8'))), [ws.quote nl]);
664676
else
665677
if (size(item, 1) == 1)
666678
% Row vector, store only column indices.
@@ -690,15 +702,15 @@
690702
fulldata = [real(item(:)) imag(item(:))]';
691703
end
692704
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipSize_":', regexprep(mat2str(size(fulldata)), '\s+', ','), sep);
693-
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, ['"' sep]);
705+
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipType_":"', dozip, [ws.quote sep]);
694706
encodeparam = {};
695707
if (~isempty(regexp(dozip, '^blosc2', 'once')))
696708
compfun = @blosc2encode;
697709
encodeparam = {dozip, 'nthread', jsonopt('nthread', 1, opt), 'shuffle', jsonopt('shuffle', 1, opt), 'typesize', jsonopt('typesize', length(typecast(fulldata(1), 'uint8')), opt)};
698710
else
699711
compfun = str2func([dozip 'encode']);
700712
end
701-
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', char(base64encode(compfun(typecast(fulldata(:), 'uint8'), encodeparam{:}))), ['"' nl]);
713+
txt = sprintf(dataformat, txt, padding0, '"_ArrayZipData_":"', char(base64encode(compfun(typecast(fulldata(:), 'uint8'), encodeparam{:}))), [ws.quote nl]);
702714
else
703715
if (isreal(item))
704716
txt = sprintf(dataformat, txt, padding0, '"_ArrayData_":', ...
@@ -711,7 +723,7 @@
711723
end
712724
end
713725

714-
txt = sprintf('%s%s%s', txt, padding1, '}');
726+
txt = sprintf('%s%s%s', txt, padding1, ws.obj(2));
715727

716728
%% -------------------------------------------------------------------------
717729
function txt = matlabobject2json(name, item, level, varargin)
@@ -775,15 +787,15 @@
775787
post = '';
776788
level = level - 1;
777789
else
778-
pre = sprintf('[%s', nl);
779-
post = sprintf('%s%s]', nl, repmat(tab, 1, level - 1));
790+
pre = sprintf('%s%s', ws.array(1), nl);
791+
post = sprintf('%s%s%s', nl, repmat(tab, 1, level - 1), ws.array(2));
780792
end
781793

782794
if (isempty(mat))
783795
if (varargin{1}.emptyarrayasnull)
784796
txt = 'null';
785797
else
786-
txt = '[]';
798+
txt = ws.array;
787799
end
788800
return
789801
end
@@ -795,7 +807,7 @@
795807
if (numel(mat) == 1 && varargin{1}.singletarray == 0 && level > 0)
796808
formatstr = [repmat([floatformat ','], 1, size(mat, 2) - 1) [floatformat sprintf(',%s', nl)]];
797809
else
798-
formatstr = ['[' repmat([floatformat ','], 1, size(mat, 2) - 1) [floatformat sprintf('],%s', nl)]];
810+
formatstr = [ws.array(1), repmat([floatformat ','], 1, size(mat, 2) - 1) [floatformat sprintf('%s,%s', ws.array(2), nl)]];
799811
end
800812
if (nargin >= 2 && size(mat, 1) > 1 && varargin{1}.arrayindent == 1)
801813
formatstr = [repmat(tab, 1, level) formatstr];

0 commit comments

Comments
 (0)