Skip to content

Commit 9d0fd4a

Browse files
committed
rewrite jdataencode
1 parent ff6e64b commit 9d0fd4a

File tree

1 file changed

+168
-18
lines changed

1 file changed

+168
-18
lines changed

jdataencode.m

+168-18
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,178 @@
1-
function newdata=jdataencode(data,varargin)
1+
function jdata=jdencode(data, varargin)
22
%
3-
% newdata=jdataencode(data,opt,...)
3+
% jdata=jdencode(data)
4+
% or
5+
% jdata=jdencode(data, options)
6+
% jdata=jdencode(data, 'Param1',value1, 'Param2',value2,...)
47
%
5-
% encode special MATLAB objects (cells, structs, sparse and complex arrays,
6-
% maps, graphs, function handles, etc) to the JData format
8+
% Serialize a MATLAB struct or cell array into a JData-compliant
9+
% structure as defined in the JData spec: http://github.com/fangq/jdata
710
%
8-
% authors:Qianqian Fang (q.fang <at> neu.edu)
11+
% author: Qianqian Fang (q.fang <at> neu.edu)
912
%
10-
% input:
11-
% data: a matlab object
12-
% opt: (optional) a list of 'Param',value pairs for additional options.
13-
% For all supported options, please see the help info for savejson.m
14-
% and loadjson.m
13+
% input:
14+
% data: a structure (array) or cell (array) to be encoded.
15+
% options: (optional) a struct or Param/value pairs for user specified options
16+
% Compression: ['zlib'|'gzip','lzma','lz4','lz4hc'] - use zlib method
17+
% to compress data array
18+
% CompressArraySize: [100|int]: only to compress an array if the
19+
% total element count is larger than this number.
1520
%
16-
% output:
17-
% newdata: the covnerted data containing JData structures
21+
% example:
22+
% jd=jdencode(struct('a',rand(5)+1i*rand(5),'b',[],'c',sparse(5,5)))
1823
%
19-
% examples:
20-
% jd=jdataencode(struct('a',rand(5)+1i*rand(5),'b',[],'c',sparse(5,5)))
21-
%
22-
% license:
23-
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
24+
% license:
25+
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
2426
%
2527
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
2628
%
2729

28-
newdata=loadjson(savejson('',data,varargin{:}),varargin{:},'JDataDecode',0);
30+
31+
if(nargin==0)
32+
help jdencode
33+
return;
34+
end
35+
36+
opt=varargin2struct(varargin{:});
37+
opt.prefix=jsonopt('Prefix',sprintf('x0x%X','_'+0),opt);
38+
39+
jdata=obj2jd(data,opt);
40+
41+
%%-------------------------------------------------------------------------
42+
function newitem=obj2jd( item,varargin)
43+
44+
if(iscell(item))
45+
newitem=cell2jd(item,varargin{:});
46+
elseif(isstruct(item))
47+
newitem=struct2jd(item,varargin{:});
48+
elseif(ischar(item) || isa(item,'string'))
49+
newitem=mat2jd(item,varargin{:});
50+
elseif(isa(item,'containers.Map'))
51+
newitem=map2jd(item,varargin{:});
52+
elseif(isa(item,'categorical'))
53+
newitem=cell2jd(cellstr(item),varargin{:});
54+
elseif(islogical(item) || isnumeric(item))
55+
newitem=mat2jd(item,varargin{:});
56+
elseif(isa(item,'table'))
57+
newitem=table2jd(item,varargin{:});
58+
elseif(isa(item,'digraph'))
59+
newitem=graph2jd(item,varargin{:});
60+
else
61+
newitem=any2jd(item,varargin{:});
62+
end
63+
64+
%%-------------------------------------------------------------------------
65+
function newitem=cell2jd(item,varargin)
66+
67+
newitem=cellfun(@(x) obj2jd(x, varargin{:}), item, 'UniformOutput',false);
68+
69+
%%-------------------------------------------------------------------------
70+
function newitem=struct2jd(item,varargin)
71+
72+
num=numel(item);
73+
if(num>1)
74+
newitem=obj2jd(num2cell(item),varargin{:});
75+
try
76+
newitem=cell2mat(newitem);
77+
catch
78+
end
79+
else
80+
names=fieldnames(item);
81+
newitem=struct;
82+
for i=1:length(names)
83+
newitem.(names{i})=obj2jd(item.(names{i}),varargin{:});
84+
end
85+
end
86+
87+
%%-------------------------------------------------------------------------
88+
function newitem=map2jd(item,varargin)
89+
90+
names=item.keys;
91+
newitem=containers.Map;
92+
for i=1:length(names)
93+
newitem(names{i})=obj2jd(item(names{i}),varargin{:});
94+
end
95+
96+
%%-------------------------------------------------------------------------
97+
function newitem=mat2jd(item,varargin)
98+
if(isa(item,'string') || ischar(item) || (isvector(item) && isreal(item) && ~issparse(item)))
99+
newitem=item;
100+
return;
101+
end
102+
103+
zipmethod=jsonopt('Compression','',varargin{:});
104+
minsize=jsonopt('CompressArraySize',100,varargin{:});
105+
106+
if(isa(item,'logical'))
107+
item=uint8(item);
108+
end
109+
110+
newitem=struct(N_('_ArraySize_'),size(item),N_('_ArrayType_'),class(item));
111+
112+
if(isreal(item))
113+
if(issparse(item))
114+
fulldata=full(item(find(item)));
115+
newitem.(N_('_ArrayIsSparse_'))=true;
116+
newitem.(N_('_ArrayZipSize_'))=[2+(~isvector(item)),length(fulldata)];
117+
if(isvector(item))
118+
newitem.(N_('_ArrayData_'))=[find(item)', fulldata(:)'];
119+
else
120+
[ix,iy]=find(item);
121+
newitem.(N_('_ArrayData_'))=[ix(:)' , iy(:)', fulldata(:)'];
122+
end
123+
else
124+
item=permute(item,ndims(item):-1:1);
125+
newitem.(N_('_ArrayData_'))=item(:)';
126+
end
127+
else
128+
newitem.(N_('_ArrayIsComplex_'))=true;
129+
if(issparse(item))
130+
fulldata=full(item(find(item)));
131+
newitem.(N_('_ArrayIsSparse_'))=true;
132+
newitem.(N_('_ArrayZipSize_'))=[3+(~isvector(item)),length(fulldata)];
133+
if(isvector(item))
134+
newitem.(N_('_ArrayData_'))=[find(item)', real(fulldata(:)'), imag(fulldata(:)')];
135+
else
136+
[ix,iy]=find(item);
137+
newitem.(N_('_ArrayData_'))=[ix(:)' , iy(:)' , real(fulldata(:)'), imag(fulldata(:)')];
138+
end
139+
else
140+
newitem.(N_('_ArrayZipSize_'))=[2,numel(item)];
141+
newitem.(N_('_ArrayData_'))=[real(item(:)'), imag(item(:)')];
142+
end
143+
end
144+
145+
if(~isempty(zipmethod) && numel(item)>minsize)
146+
compfun=str2func([zipmethod 'encode']);
147+
newitem.(N_('_ArrayZipType_'))=lower(zipmethod);
148+
newitem.(N_('_ArrayZipSize_'))=size(newitem.(N_('_ArrayData_')));
149+
newitem.(N_('_ArrayZipData_'))=compfun(typecast(newitem.(N_('_ArrayData_')),'uint8'));
150+
newitem=rmfield(newitem,N_('_ArrayData_'));
151+
if(jsonopt('Base64',1,varargin{:}))
152+
newitem.(N_('_ArrayZipData_'))=char(base64encode(newitem.(N_('_ArrayZipData_'))));
153+
end
154+
end
155+
156+
%%-------------------------------------------------------------------------
157+
function newitem=table2jd(item,varargin)
158+
newitem=struct;
159+
newitem(N_('_TableRows_'))=item.Properties.RowNames';
160+
newitem(N_('_TableCols_'))=item.Properties.VariableNames;
161+
newitem(N_('_TableRecords_'))=table2cell(item);
162+
163+
%%-------------------------------------------------------------------------
164+
function newitem=graph2jd(item,varargin)
165+
newitem=struct;
166+
nodedata=table2struct(item.Nodes);
167+
if(any(ismember(G.Edges.Properties.VariableNames,'Name')))
168+
nodedata=rmfield(nodedata,'Name');
169+
newitem(N_('_GraphNodes_'))=containers.Map(item.Nodes.Name,num2cell(nodedata),'uniformValues',false);
170+
else
171+
newitem(N_('_GraphNodes_'))=containers.Map(1:max(item.Edges.EndNodes(:)),num2cell(nodedata),'uniformValues',false);
172+
end
173+
newitem(N_('_GraphEdges_'))=num2cell(table2cell(item.Edges),2);
174+
175+
%%-------------------------------------------------------------------------
176+
function newname=N_(name,varargin)
177+
prefix=jsonopt('Prefix',sprintf('x0x%X','_'+0),varargin{:});
178+
newname=[prefix name];

0 commit comments

Comments
 (0)