-
Notifications
You must be signed in to change notification settings - Fork 2
/
json2mat.m
168 lines (156 loc) · 4.56 KB
/
json2mat.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
function M=json2mat(J,tag)
%JSON2MAT converts a javscript data object (JSON) into a Matlab structure
% using s recursive approach. J can also be a file name.
%
%Example: lala=json2mat('{lele:2,lili:4,lolo:[1,2,{lulu:5,bubu:[[1,2],[3,4],[5,6]]}]}')
% notice lala.lolo{3}.bubu is read as a 2D matrix.
%
% Jonas Almeida, March 2010
if exist('tag')~=1
tag={};
end
if exist(J)==2 % if J is a filename
fid=fopen(J,'r');
J='';
while ~feof(fid)
J=[J,fgetl(fid)];
end
fclose(fid);
M=json2mat(J);
else
J1=regexprep(J(1:min([5,length(J)])),'\s',''); %despaced start of J string
if isempty(J1)
M='';
elseif J1(1)=='{' %extract structures
JJ=regexp(J,'\{(.*)\}','tokens');
if ~isempty(JJ)
M=extract_struct(JJ{1}{1},tag);
else
M={};
end
elseif J1(1)=='[' %extract cells
JJ=regexp(J,'\[(.*)\]','tokens');
if ~isempty(JJ)
M=extract_cell(JJ{1}{1});
else
M=[];
end
elseif J1(1)=='"' %literal string
JJ=regexp(J,'\"(.*)\"','tokens');
if ~isempty(JJ)
M=JJ{1}{1};
else
M='';
end
else %numeric value
j=regexp(J,'[\s*-\d\.\E\e]');
if length(j)==length(J) %it is a number
M=str2num(J); % is number
else
M=json2mat(['"',J,'"']); % not a number after all
end
end
end
function y=extract_struct(x,tag)
%detag arrays first
indOC=extract_embed(x,'[',']');
n=size(indOC,1);
for i=n:-1:1
tag{i}=json2mat(x(indOC(i,1):indOC(i,2)));
x=[x(1:indOC(i,1)-1),'tag~<',num2str(i),'>~',x(indOC(i,2)+1:end)];
end
%detag nested structures next
indOC=extract_embed(x,'{','}');
m=size(indOC,1);
for i=n+m:-1:n+1
j=i-n;
tag{i}=json2mat(x(indOC(j,1):indOC(j,2)),tag);
x=[x(1:indOC(j,1)-1),'tag{',num2str(i),'}',x(indOC(j,2)+1:end)];
end
x=strrep(x,'~<','{');
x=strrep(x,'>~','}');
a=regexp(x,'[^:,]+:[^,]+');
n=length(a);
a=[a,length(x)+2];
for i=1:n
s=x(a(i):a(i+1)-2);
t=regexp(s,'([^:]+):(.+)','tokens');
%t{1}{1}(t{1}{1}==32)=[]; % remove blanks, maybe later do something fancier like replace with underscores
t{1}{1}=strrep(t{1}{1},' ','_');
t{1}{1}=strrep(t{1}{1},'"','');
if t{1}{1}(1)=='_' %JSON allows for fieldnames starting with "_"
t{1}{1}(1)=''; % this line will cause hard to track problems if the same object has 2 attributes with the same name but one of them starting with "_"
end
t{1}{1}=regexprep(t{1}{1},'\W','_'); %for example to deal with couch attachements
if regexp(t{1}{2},'tag{\d+}')
y.(t{1}{1})=eval(t{1}{2});
else
y.(t{1}{1})=json2mat(t{1}{2});
end
%y.(t{1}{1})=json2mat(t{1}{2});
end
function y=extract_cell(x)
indOC=extract_embed(x,'{','}');
n=size(indOC,1);
for i=n:-1:1
tag{i}=json2mat(x(indOC(i,1):indOC(i,2)));
x=[x(1:indOC(i,1)-1),'tag~<',num2str(i),'>~',x(indOC(i,2)+1:end)];
end
indOC=extract_embed(x,'[',']');
m=size(indOC,1);
for j=m:-1:1
i=n+j;
tag{i}=json2mat(x(indOC(i,1):indOC(i,2)));
try;tag{i}=cell2mat(tag{i});end
x=[x(1:indOC(i,1)-1),'tag{',num2str(i),'}',x(indOC(i,2)+1:end)];
end
x=strrep(x,'~<','{');
x=strrep(x,'>~','}');
if exist('tag') %catching numeric content
if isnumeric([tag{:}])
try
y=eval(['[',strrep(x,'},','};'),']']);
end
end
end
if exist('y')~=1
if sum(x=='"')==0
y=eval(['{',x,'}']);
try;y=cell2mat(y')';end
else
y=eval(['{',strrep(x,'"',''''),'}']);
end
end
%look for embeded objects and arrays
function y=extract_embed(x,tagOpen,tagClose)
%EXTRACT_EMBED identifies embeded tagged segments
%Example y=extract_embed(str,'[',']')
indOpen=strfind(x,tagOpen)';
indOpen=[indOpen,ones(length(indOpen),1)];
indClose=strfind(x,tagClose)';
indClose=[indClose,-ones(length(indClose),1)];
indOpenClose=[indOpen;indClose];
[lala,Ind]=sort(indOpenClose(:,1));
indOpenClose=indOpenClose(Ind,:);
n=size(indOpenClose,1);
for i=2:n % add one for open, take one for close
indOpenClose(i,2)=indOpenClose(i-1,2)+indOpenClose(i,2);
end
i=0;
op=0; %open
while i<n
i=i+1;
if (indOpenClose(i,2)==1)*(op==0)
op=1;
elseif indOpenClose(i,2)==0
op=0;
else
indOpenClose(i,2)=-1;
end
end
if isempty(indOpenClose)
y=[];
else
indOpenClose(indOpenClose(:,2)<0,:)=[];
y=[indOpenClose(1:2:end,1),indOpenClose(2:2:end,1)];% Open/Close Indexes
end