0001 function data = loadjson(fname,varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 global pos index_esc isoct arraytoken
0065
0066 if(regexp(fname,'^\s*(?:\[.*\])|(?:\{.*\})\s*$','once'))
0067 string=fname;
0068 elseif(exist(fname,'file'))
0069 try
0070 string = fileread(fname);
0071 catch
0072 try
0073 string = urlread(['file://',fname]);
0074 catch
0075 string = urlread(['file://',fullfile(pwd,fname)]);
0076 end
0077 end
0078 else
0079 error('input file does not exist');
0080 end
0081
0082 pos = 1; len = length(string); inStr = string;
0083 isoct=exist('OCTAVE_VERSION','builtin');
0084 arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
0085 jstr=regexprep(inStr,'\\\\',' ');
0086 escquote=regexp(jstr,'\\"');
0087 arraytoken=sort([arraytoken escquote]);
0088
0089
0090 esc = find(inStr=='"' | inStr=='\' );
0091 index_esc = 1;
0092
0093 opt=varargin2struct(varargin{:});
0094
0095 if(jsonopt('ShowProgress',0,opt)==1)
0096 opt.progressbar_=waitbar(0,'loading ...');
0097 end
0098 jsoncount=1;
0099 while pos <= len
0100 switch(next_char(inStr))
0101 case '{'
0102 data{jsoncount} = parse_object(inStr, esc, opt);
0103 case '['
0104 data{jsoncount} = parse_array(inStr, esc, opt);
0105 otherwise
0106 error_pos('Outer level structure must be an object or an array',inStr);
0107 end
0108 jsoncount=jsoncount+1;
0109 end
0110
0111 jsoncount=length(data);
0112 if(jsoncount==1 && iscell(data))
0113 data=data{1};
0114 end
0115
0116 if(isfield(opt,'progressbar_'))
0117 close(opt.progressbar_);
0118 end
0119
0120
0121 function object = parse_object(inStr, esc, varargin)
0122 parse_char(inStr, '{');
0123 object = [];
0124 if next_char(inStr) ~= '}'
0125 while 1
0126 str = parseStr(inStr, esc, varargin{:});
0127 if isempty(str)
0128 error_pos('Name of value at position %d cannot be empty',inStr);
0129 end
0130 parse_char(inStr, ':');
0131 val = parse_value(inStr, esc, varargin{:});
0132 object.(valid_field(str))=val;
0133 if next_char(inStr) == '}'
0134 break;
0135 end
0136 parse_char(inStr, ',');
0137 end
0138 end
0139 parse_char(inStr, '}');
0140 if(isstruct(object))
0141 object=struct2jdata(object);
0142 end
0143
0144
0145
0146 function object = parse_array(inStr, esc, varargin)
0147 global pos isoct
0148 parse_char(inStr, '[');
0149 object = cell(0, 1);
0150 dim2=[];
0151 arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:});
0152 pbar=-1;
0153 if(isfield(varargin{1},'progressbar_'))
0154 pbar=varargin{1}.progressbar_;
0155 end
0156
0157 if next_char(inStr) ~= ']'
0158 if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:}))
0159 [endpos, e1l, e1r]=matching_bracket(inStr,pos);
0160 arraystr=['[' inStr(pos:endpos)];
0161 arraystr=regexprep(arraystr,'"_NaN_"','NaN');
0162 arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf');
0163 arraystr(arraystr==sprintf('\n'))=[];
0164 arraystr(arraystr==sprintf('\r'))=[];
0165
0166 if(~isempty(e1l) && ~isempty(e1r))
0167 astr=inStr((e1l+1):(e1r-1));
0168 astr=regexprep(astr,'"_NaN_"','NaN');
0169 astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf');
0170 astr(astr==sprintf('\n'))=[];
0171 astr(astr==sprintf('\r'))=[];
0172 astr(astr==' ')='';
0173 if(isempty(find(astr=='[', 1)))
0174 dim2=length(sscanf(astr,'%f,',[1 inf]));
0175 end
0176 else
0177 astr=arraystr(2:end-1);
0178 astr(astr==' ')='';
0179 [obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]);
0180 if(nextidx>=length(astr)-1)
0181 object=obj;
0182 pos=endpos;
0183 parse_char(inStr, ']');
0184 return;
0185 end
0186 end
0187
0188 try
0189 if(~isempty(dim2))
0190 astr=arraystr;
0191 astr(astr=='[')='';
0192 astr(astr==']')='';
0193 astr=regexprep(astr,'\s*$','');
0194 astr(astr==' ')='';
0195 [obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf);
0196 if(nextidx>=length(astr)-1)
0197 object=reshape(obj,dim2,numel(obj)/dim2)';
0198 pos=endpos;
0199 parse_char(inStr, ']');
0200 if(pbar>0)
0201 waitbar(pos/length(inStr),pbar,'loading ...');
0202 end
0203 return;
0204 end
0205 end
0206 arraystr=regexprep(arraystr,'\]\s*,','];');
0207 catch
0208 end
0209 else
0210 arraystr='[';
0211 end
0212 try
0213 arraystr=regexprep(arraystr,'^\s*\[','{','once');
0214 arraystr=regexprep(arraystr,'\]\s*$','}','once');
0215 if(isoct && regexp(arraystr,'"','once'))
0216 error('Octave eval can produce empty cells for JSON-like input');
0217 end
0218 if(regexp(arraystr,':','once'))
0219 error('One can not use MATLAB-like ":" construct inside a JSON array');
0220 end
0221 object=eval(arraystr);
0222 pos=endpos;
0223 catch
0224 while 1
0225 newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1);
0226 val = parse_value(inStr, esc, newopt);
0227 object{end+1} = val;
0228 if next_char(inStr) == ']'
0229 break;
0230 end
0231 parse_char(inStr, ',');
0232 end
0233 end
0234 end
0235 if(jsonopt('SimplifyCell',0,varargin{:})==1)
0236 try
0237 oldobj=object;
0238 object=cell2mat(object')';
0239 if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
0240 object=oldobj;
0241 elseif(size(object,1)>1 && ismatrix(object))
0242 object=object';
0243 end
0244 catch
0245 end
0246 end
0247 parse_char(inStr, ']');
0248
0249 if(pbar>0)
0250 waitbar(pos/length(inStr),pbar,'loading ...');
0251 end
0252
0253
0254 function parse_char(inStr, c)
0255 global pos
0256 pos=skip_whitespace(pos, inStr);
0257 if pos > length(inStr) || inStr(pos) ~= c
0258 error_pos(sprintf('Expected %c at position %%d', c),inStr);
0259 else
0260 pos = pos + 1;
0261 pos=skip_whitespace(pos, inStr);
0262 end
0263
0264
0265
0266 function c = next_char(inStr)
0267 global pos
0268 pos=skip_whitespace(pos, inStr);
0269 if pos > length(inStr)
0270 c = [];
0271 else
0272 c = inStr(pos);
0273 end
0274
0275
0276
0277 function newpos=skip_whitespace(pos, inStr)
0278 newpos=pos;
0279 while newpos <= length(inStr) && isspace(inStr(newpos))
0280 newpos = newpos + 1;
0281 end
0282
0283
0284 function str = parseStr(inStr, esc, varargin)
0285 global pos index_esc
0286
0287 if inStr(pos) ~= '"'
0288 error_pos('String starting with " expected at position %d',inStr);
0289 else
0290 pos = pos + 1;
0291 end
0292 str = '';
0293 while pos <= length(inStr)
0294 while index_esc <= length(esc) && esc(index_esc) < pos
0295 index_esc = index_esc + 1;
0296 end
0297 if index_esc > length(esc)
0298 str = [str inStr(pos:end)];
0299 pos = length(inStr) + 1;
0300 break;
0301 else
0302 str = [str inStr(pos:esc(index_esc)-1)];
0303 pos = esc(index_esc);
0304 end
0305 nstr = length(str);
0306 switch inStr(pos)
0307 case '"'
0308 pos = pos + 1;
0309 if(~isempty(str))
0310 if(strcmp(str,'_Inf_'))
0311 str=Inf;
0312 elseif(strcmp(str,'-_Inf_'))
0313 str=-Inf;
0314 elseif(strcmp(str,'_NaN_'))
0315 str=NaN;
0316 end
0317 end
0318 return;
0319 case '\'
0320 if pos+1 > length(inStr)
0321 error_pos('End of file reached right after escape character',inStr);
0322 end
0323 pos = pos + 1;
0324 switch inStr(pos)
0325 case {'"' '\' '/'}
0326 str(nstr+1) = inStr(pos);
0327 pos = pos + 1;
0328 case {'b' 'f' 'n' 'r' 't'}
0329 str(nstr+1) = sprintf(['\' inStr(pos)]);
0330 pos = pos + 1;
0331 case 'u'
0332 if pos+4 > length(inStr)
0333 error_pos('End of file reached in escaped unicode character',inStr);
0334 end
0335 str(nstr+(1:6)) = inStr(pos-1:pos+4);
0336 pos = pos + 5;
0337 end
0338 otherwise
0339 str(nstr+1) = inStr(pos);
0340 keyboard;
0341 pos = pos + 1;
0342 end
0343 end
0344 error_pos('End of file while expecting end of inStr',inStr);
0345
0346
0347
0348 function num = parse_number(inStr, varargin)
0349 global pos isoct
0350 currstr=inStr(pos:min(pos+30,end));
0351 if(isoct~=0)
0352 numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end');
0353 [num] = sscanf(currstr, '%f', 1);
0354 delta=numstr+1;
0355 else
0356 [num, one, err, delta] = sscanf(currstr, '%f', 1);
0357 if ~isempty(err)
0358 error_pos('Error reading number at position %d',inStr);
0359 end
0360 end
0361 pos = pos + delta-1;
0362
0363
0364
0365 function val = parse_value(inStr, esc, varargin)
0366 global pos
0367 len=length(inStr);
0368 if(isfield(varargin{1},'progressbar_'))
0369 waitbar(pos/len,varargin{1}.progressbar_,'loading ...');
0370 end
0371
0372 switch(inStr(pos))
0373 case '"'
0374 val = parseStr(inStr, esc, varargin{:});
0375 return;
0376 case '['
0377 val = parse_array(inStr, esc, varargin{:});
0378 return;
0379 case '{'
0380 val = parse_object(inStr, esc, varargin{:});
0381 return;
0382 case {'-','0','1','2','3','4','5','6','7','8','9'}
0383 val = parse_number(inStr, varargin{:});
0384 return;
0385 case 't'
0386 if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true')
0387 val = true;
0388 pos = pos + 4;
0389 return;
0390 end
0391 case 'f'
0392 if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false')
0393 val = false;
0394 pos = pos + 5;
0395 return;
0396 end
0397 case 'n'
0398 if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null')
0399 val = [];
0400 pos = pos + 4;
0401 return;
0402 end
0403 end
0404 error_pos('Value expected at position %d',inStr);
0405
0406
0407 function error_pos(msg, inStr)
0408 global pos len
0409 poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
0410 if poShow(3) == poShow(2)
0411 poShow(3:4) = poShow(2)+[0 -1];
0412 end
0413 msg = [sprintf(msg, pos) ': ' ...
0414 inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
0415 error( ['JSONparser:invalidFormat: ' msg] );
0416
0417
0418
0419 function str = valid_field(str)
0420 global isoct
0421
0422
0423
0424
0425 pos=regexp(str,'^[^A-Za-z]','once');
0426 if(~isempty(pos))
0427 if(~isoct && str(1)+0 > 255)
0428 str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
0429 else
0430 str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
0431 end
0432 end
0433 if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' )))
0434 return;
0435 end
0436 if(~isoct)
0437 str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
0438 else
0439 pos=regexp(str,'[^0-9A-Za-z_]');
0440 if(isempty(pos))
0441 return;
0442 end
0443 str0=str;
0444 pos0=[0 pos(:)' length(str)];
0445 str='';
0446 for i=1:length(pos)
0447 str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
0448 end
0449 if(pos(end)~=length(str))
0450 str=[str str0(pos0(end-1)+1:pos0(end))];
0451 end
0452 end
0453
0454
0455
0456 function endpos = matching_quote(str,pos)
0457 len=length(str);
0458 while(pos<len)
0459 if(str(pos)=='"')
0460 if(~(pos>1 && str(pos-1)=='\'))
0461 endpos=pos;
0462 return;
0463 end
0464 end
0465 pos=pos+1;
0466 end
0467 error('unmatched quotation mark');
0468
0469 function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos)
0470 global arraytoken
0471 level=1;
0472 maxlevel=level;
0473 endpos=0;
0474 bpos=arraytoken(arraytoken>=pos);
0475 tokens=str(bpos);
0476 len=length(tokens);
0477 pos=1;
0478 e1l=[];
0479 e1r=[];
0480 while(pos<=len)
0481 c=tokens(pos);
0482 if(c==']')
0483 level=level-1;
0484 if(isempty(e1r))
0485 e1r=bpos(pos);
0486 end
0487 if(level==0)
0488 endpos=bpos(pos);
0489 return
0490 end
0491 elseif(c=='[')
0492 if(isempty(e1l))
0493 e1l=bpos(pos);
0494 end
0495 level=level+1;
0496 maxlevel=max(maxlevel,level);
0497 elseif(c=='"')
0498 pos=matching_quote(tokens,pos+1);
0499 end
0500 pos=pos+1;
0501 end
0502 if(endpos==0)
0503 error('unmatched "]"');
0504 end