Skip to content

Commit e1d386d

Browse files
committed
[feat] support saving dictionary to json and bjdata
1 parent dfc744b commit e1d386d

File tree

5 files changed

+79
-18
lines changed

5 files changed

+79
-18
lines changed

jdataencode.m

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
newitem = mat2jd(item, varargin{:});
108108
elseif (ischar(item) || isa(item, 'string'))
109109
newitem = mat2jd(item, varargin{:});
110-
elseif (isa(item, 'containers.Map'))
110+
elseif (isa(item, 'containers.Map') || isa(item, 'dictionary'))
111111
newitem = map2jd(item, varargin{:});
112112
elseif (isa(item, 'categorical'))
113113
newitem = cell2jd(cellstr(item), varargin{:});
@@ -166,13 +166,21 @@
166166
end
167167
end
168168
else % keep as a map and only encode its values
169-
if (strcmp(item.KeyType, 'char'))
169+
if (isa(item, 'dictionary'))
170+
newitem = dictionary();
171+
elseif (strcmp(item.KeyType, 'char'))
170172
newitem = containers.Map();
171173
else
172174
newitem = containers.Map('KeyType', item.KeyType, 'ValueType', 'any');
173175
end
174-
for i = 1:length(names)
175-
newitem(names{i}) = obj2jd(item(names{i}), varargin{:});
176+
if (isa(item, 'dictionary'))
177+
for i = 1:length(names)
178+
newitem(names(i)) = obj2jd(item(names(i)), varargin{:});
179+
end
180+
else
181+
for i = 1:length(names)
182+
newitem(names{i}) = obj2jd(item(names{i}), varargin{:});
183+
end
176184
end
177185
end
178186

loadjson.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@
282282
mmap = filterjsonmmap(mmap, jsonopt('MMapInclude', {}, opt), 1);
283283
mmap = cellfun(@(x) {x{1}, x{2}(1:(2 + int8(length(x{2}) >= 3 && (x{2}(3) > 0))))}, mmap, 'UniformOutput', false);
284284
end
285-
if (jsonopt('JDataDecode', 1, varargin{:}) == 1)
285+
if (jsonopt('JDataDecode', 1, opt) == 1)
286286
try
287-
data = jdatadecode(data, 'Base64', 1, 'Recursive', 1, varargin{:});
287+
data = jdatadecode(data, 'Base64', 1, 'Recursive', 1, opt);
288288
catch ME
289289
warning(['Failed to decode embedded JData annotations, '...
290290
'return raw JSON data\n\njdatadecode error: %s\n%s\nCall stack:\n%s\n'], ...

savebj.m

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@
316316
end
317317
elseif (isa(item, 'function_handle'))
318318
txt = struct2ubjson(name, functions(item), level, varargin{:});
319-
elseif (isa(item, 'containers.Map'))
319+
elseif (isa(item, 'containers.Map') || isa(item, 'dictionary'))
320320
txt = map2ubjson(name, item, level, varargin{:});
321321
elseif (isa(item, 'categorical'))
322322
txt = cell2ubjson(name, cellstr(item), level, varargin{:});
@@ -469,12 +469,28 @@
469469
%% -------------------------------------------------------------------------
470470
function txt = map2ubjson(name, item, level, varargin)
471471
txt = '';
472-
if (~isa(item, 'containers.Map'))
473-
error('input is not a struct');
474-
end
472+
itemtype = isa(item, 'containers.Map');
475473
dim = size(item);
474+
475+
if (isa(item, 'dictionary'))
476+
itemtype = 2;
477+
dim = item.numEntries;
478+
end
479+
if (itemtype == 0)
480+
error('input is not a containers.Map or dictionary class');
481+
end
482+
476483
names = keys(item);
477484
val = values(item);
485+
486+
if (~iscell(names))
487+
names = num2cell(names, ndims(names));
488+
end
489+
490+
if (~iscell(val))
491+
val = num2cell(val, ndims(val));
492+
end
493+
478494
Omarker = varargin{1}.OM_;
479495

480496
if (~strcmp(Omarker{1}, '{'))
@@ -495,6 +511,9 @@
495511
end
496512
end
497513
txt = [txt Omarker{2}];
514+
if (isa(txt, 'string') && length(txt) > 1)
515+
txt = sprintf('%s', txt);
516+
end
498517

499518
%% -------------------------------------------------------------------------
500519
function txt = str2ubjson(name, item, level, varargin)
@@ -841,6 +860,7 @@
841860
%% -------------------------------------------------------------------------
842861
function val = N_(str, varargin)
843862
ismsgpack = varargin{1}.messagepack;
863+
str = char(str);
844864
if (~ismsgpack)
845865
val = [I_(int32(length(str)), varargin{:}) str];
846866
else

savejson.m

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
if (isempty(regexp(json, '^[{\[]', 'once')))
177177
json = ['[', json, ']'];
178178
end
179+
if (nargout > 0)
180+
output = json;
181+
end
179182
return
180183
catch
181184
warning('built-in jsonencode function failed to encode the data, fallback to savejson');
@@ -218,7 +221,7 @@
218221
rootname = varname;
219222
end
220223
end
221-
if (isa(obj, 'containers.Map') && ~strcmp(obj.KeyType, 'char'))
224+
if ((isa(obj, 'containers.Map') && ~strcmp(obj.KeyType, 'char')) || (isa(obj, 'dictionary') && ~strcmp(obj.types, 'string')))
222225
rootisarray = 0;
223226
end
224227
if ((isstruct(obj) || iscell(obj)) && isempty(rootname) && forceroot)
@@ -300,7 +303,7 @@
300303
end
301304
elseif (isa(item, 'function_handle'))
302305
txt = struct2json(name, functions(item), level, varargin{:});
303-
elseif (isa(item, 'containers.Map'))
306+
elseif (isa(item, 'containers.Map') || isa(item, 'dictionary'))
304307
txt = map2json(name, item, level, varargin{:});
305308
elseif (isa(item, 'categorical'))
306309
txt = cell2json(name, cellstr(item), level, varargin{:});
@@ -451,14 +454,28 @@
451454
%% -------------------------------------------------------------------------
452455
function txt = map2json(name, item, level, varargin)
453456
txt = {};
454-
if (~isa(item, 'containers.Map'))
455-
error('input is not a containers.Map class');
456-
end
457+
itemtype = isa(item, 'containers.Map');
457458
dim = size(item);
459+
460+
if (isa(item, 'dictionary'))
461+
itemtype = 2;
462+
dim = item.numEntries;
463+
end
464+
if (itemtype == 0)
465+
error('input is not a containers.Map or dictionary class');
466+
end
458467
names = keys(item);
459468
val = values(item);
460469

461-
if (~strcmp(item.KeyType, 'char'))
470+
if (~iscell(names))
471+
names = num2cell(names, ndims(names));
472+
end
473+
474+
if (~iscell(val))
475+
val = num2cell(val, ndims(val));
476+
end
477+
478+
if ((itemtype == 1 && ~strcmp(item.KeyType, 'char')) || (itemtype == 2 && ~strcmp(item.types, 'string')))
462479
mm = cell(1, length(names));
463480
for i = 1:length(names)
464481
mm{i} = {names{i}, val{i}};

test/run_jsonlab_test.m

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,18 @@ function run_jsonlab_test(tests)
101101
'{"x0x5F_i":1,"i_":"str"}', 'compact', 1, 'UnpackHex', 0);
102102
end
103103
if (exist('containers.Map'))
104-
test_jsonlab('containers.Map', @savejson, containers.Map({'Andy', '^_^'}, {true, '-_-'}), ...
104+
test_jsonlab('containers.Map with char keys', @savejson, containers.Map({'Andy', '^_^'}, {true, '-_-'}), ...
105105
'{"Andy":true,"^_^":"-_-"}', 'compact', 1, 'usemap', 1);
106+
test_jsonlab('containers.Map with number keys', @savejson, containers.Map({1.1, 1.2}, {true, '-_-'}), ...
107+
'{"_MapData_":[[1.1,true],[1.2,"-_-"]]}', 'compact', 1, 'usemap', 1);
108+
end
109+
if (exist('dictionary'))
110+
test_jsonlab('dictionary with string keys', @savejson, dictionary(["Andy", "^_^"], {true, '-_-'}), ...
111+
'{"Andy":true,"^_^":"-_-"}', 'compact', 1, 'usemap', 1);
112+
test_jsonlab('dictionary with cell keys', @savejson, dictionary({'Andy', '^_^'}, {true, '-_-'}), ...
113+
'{"_MapData_":[["Andy",true],["^_^","-_-"]]}', 'compact', 1, 'usemap', 1);
114+
test_jsonlab('dictionary with number keys', @savejson, dictionary({1.1, 1.2}, {true, '-_-'}), ...
115+
'{"_MapData_":[[1.1,true],[1.2,"-_-"]]}', 'compact', 1, 'usemap', 1);
106116
end
107117
if (exist('istable'))
108118
test_jsonlab('simple table', @savejson, table({'Andy', '^_^'}, {true, '-_-'}), ...
@@ -238,8 +248,14 @@ function run_jsonlab_test(tests)
238248
'{U<7>x0x5F_iU<1>U<2>i_SU<3>str}', 'debug', 1, 'UnpackHex', 0);
239249
end
240250
if (exist('containers.Map'))
241-
test_jsonlab('containers.Map', @savebj, containers.Map({'Andy', '^_^'}, {true, '-_-'}), ...
251+
test_jsonlab('containers.Map with char keys', @savebj, containers.Map({'Andy', '^_^'}, {true, '-_-'}), ...
252+
'{U<4>AndyTU<3>^_^SU<3>-_-}', 'debug', 1, 'usemap', 1);
253+
end
254+
if (exist('dictionary'))
255+
test_jsonlab('dictionary with string keys', @savebj, dictionary(["Andy", "^_^"], {true, '-_-'}), ...
242256
'{U<4>AndyTU<3>^_^SU<3>-_-}', 'debug', 1, 'usemap', 1);
257+
test_jsonlab('dictionary with cell keys', @savebj, dictionary({'Andy', '^_^'}, {true, '-_-'}), ...
258+
'{U<4>AndyTU<3>^_^SU<3>-_-}', 'debug', 1, 'usemap', 1);
243259
end
244260
if (exist('istable'))
245261
test_jsonlab('simple table', @savebj, table({'Andy', '^_^'}, {true, '-_-'}), ...

0 commit comments

Comments
 (0)