diff --git a/ChangeLog.txt b/ChangeLog.txt index bfc028fdb2a19acec2c6150e4b0032eb87bc9181..853734c23806a402872adf108d92931f114c990d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -6,10 +6,17 @@ JSONlab ChangeLog (key features marked by *): +== JSONlab 0.9.0 (codename: Rodimus), FangQ <fangq (at) nmr.mgh.harvard.edu> == + + 2012/06/17 *new format for an invalid leading char, unpacking hex code in savejson + 2012/06/01 support JSONP in savejson + 2012/05/25 fix the empty cell bug (reported by Cyril Davin) + 2012/04/05 savejson can save to a file (suggested by Patrick Rapin) + == JSONlab 0.8.1 (codename: Sentiel, Update 1), FangQ <fangq (at) nmr.mgh.harvard.edu> == - 2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS - 2012/01/25 patch to handle root-less objects, contributed by Blake Johnson + 2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS + 2012/01/25 patch to handle root-less objects, contributed by Blake Johnson == JSONlab 0.8.0 (codename: Sentiel), FangQ <fangq (at) nmr.mgh.harvard.edu> == diff --git a/examples/jsonlab_basictest.matlab b/examples/jsonlab_basictest.matlab index 97f60fd82c907ca6b82aac6dae2ae50336634f78..ff8380a1d2447054a939b40df143c61c632511a4 100644 --- a/examples/jsonlab_basictest.matlab +++ b/examples/jsonlab_basictest.matlab @@ -353,9 +353,9 @@ json2data = >> >> json2data = - ValidName: 1 - x_InvalidName: 2 - x_0x3A_Field_0x3A_: 3 - x_0xE9A1B9__0xE79BAE_: '绝密' + ValidName: 1 + x0x5F_InvalidName: 2 + x0x3A_Field_0x3A_: 3 + x0xE9A1B9__0xE79BAE_: '绝密' >> >> >> >> \ No newline at end of file diff --git a/loadjson.m b/loadjson.m index e4f79dec1ec4eeda7cb816fba99d60d04c1088f9..480b33d818e69b7c11518e7445f130a033dedd7d 100644 --- a/loadjson.m +++ b/loadjson.m @@ -121,33 +121,33 @@ for i=1:length(fn) % depth-first end end end -if(~isempty(strmatch('x_ArrayType_',fn)) && ~isempty(strmatch('x_ArrayData_',fn))) +if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && ~isempty(strmatch('x0x5F_ArrayData_',fn))) newdata=cell(len,1); for j=1:len - ndata=cast(data(j).x_ArrayData_,data(j).x_ArrayType_); + ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_); iscpx=0; - if(~isempty(strmatch('x_ArrayIsComplex_',fn))) - if(data(j).x_ArrayIsComplex_) + if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn))) + if(data(j).x0x5F_ArrayIsComplex_) iscpx=1; end end - if(~isempty(strmatch('x_ArrayIsSparse_',fn))) - if(data(j).x_ArrayIsSparse_) + if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn))) + if(data(j).x0x5F_ArrayIsSparse_) if(iscpx && size(ndata,2)==4) ndata(:,3)=complex(ndata(:,3),ndata(:,4)); end - if(~isempty(strmatch('x_ArraySize_',fn))) - dim=data(j).x_ArraySize_; + if(~isempty(strmatch('x0x5F_ArraySize_',fn))) + dim=data(j).x0x5F_ArraySize_; ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end))); else ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3)); end end - elseif(~isempty(strmatch('x_ArraySize_',fn))) + elseif(~isempty(strmatch('x0x5F_ArraySize_',fn))) if(iscpx && size(ndata,2)==2) ndata=complex(ndata(:,1),ndata(:,2)); end - ndata=reshape(ndata(:),data(j).x_ArraySize_); + ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_); end newdata{j}=ndata; end @@ -421,9 +421,14 @@ global isoct % From MATLAB doc: field names must begin with a letter, which may be % followed by any combination of letters, digits, and underscores. % Invalid characters will be converted to underscores, and the prefix -% "x_" will be added if first character is not a letter. - if ~isletter(str(1)) || str(1)>'z' - str = ['x' str]; +% "x0x[Hex code]_" will be added if the first character is not a letter. + pos=regexp(str,'^[^A-Za-z]','once'); + if(~isempty(pos)) + if(~isoct) + str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once'); + else + str=sprintf('x0x%X_%s',char(str(1)),str(2:end)); + end end if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' ))) return; end if(~isoct) diff --git a/savejson.m b/savejson.m index da6431d3aca4abd808f353fc51ec4bd904aedb5b..27995b743f4a6cc5cd0ddfe8b9fdb3a0bdc6f893 100644 --- a/savejson.m +++ b/savejson.m @@ -57,6 +57,8 @@ function json=savejson(rootname,obj,varargin) % opt.JSONP [''|string]: to generate a JSONP output (JSON with padding), % for example, if opt.JSON='foo', the JSON data is % wrapped inside a function call as 'foo(...);' +% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson +% back to the string form % opt can be replaced by a list of ('param',value) pairs. The param % string is equivallent to a field in opt. % output: @@ -80,6 +82,7 @@ if(length(varargin)==1 && ischar(varargin{1})) else opt=varargin2struct(varargin{:}); end +opt.IsOctave=exist('OCTAVE_VERSION'); rootisarray=0; rootlevel=1; forceroot=jsonopt('ForceRootName',0,opt); @@ -139,13 +142,13 @@ padding1=repmat(sprintf('\t'),1,level-1); padding0=repmat(sprintf('\t'),1,level); if(len>1) if(~isempty(name)) - txt=sprintf('%s"%s": [\n',padding0, name); name=''; + txt=sprintf('%s"%s": [\n',padding0, checkname(name,varargin{:})); name=''; else txt=sprintf('%s[\n',padding0); end elseif(len==0) if(~isempty(name)) - txt=sprintf('%s"%s": null',padding0, name); name=''; + txt=sprintf('%s"%s": null',padding0, checkname(name,varargin{:})); name=''; else txt=sprintf('%snull',padding0); end @@ -168,14 +171,14 @@ padding0=repmat(sprintf('\t'),1,level); sep=','; if(~isempty(name)) - if(len>1) txt=sprintf('%s"%s": [\n',padding0,name); end + if(len>1) txt=sprintf('%s"%s": [\n',padding0,checkname(name,varargin{:})); end else if(len>1) txt=sprintf('%s[\n',padding0); end end for e=1:len names = fieldnames(item(e)); if(~isempty(name) && len==1) - txt=sprintf('%s%s"%s": {\n',txt,repmat(sprintf('\t'),1,level+(len>1)), name); + txt=sprintf('%s%s"%s": {\n',txt,repmat(sprintf('\t'),1,level+(len>1)), checkname(name,varargin{:})); else txt=sprintf('%s%s{\n',txt,repmat(sprintf('\t'),1,level+(len>1))); end @@ -207,11 +210,11 @@ padding1=repmat(sprintf('\t'),1,level); padding0=repmat(sprintf('\t'),1,level+1); if(~isempty(name)) - if(len>1) txt=sprintf('%s"%s": [\n',padding1,name); end + if(len>1) txt=sprintf('%s"%s": [\n',padding1,checkname(name,varargin{:})); end else if(len>1) txt=sprintf('%s[\n',padding1); end end -isoct=exist('OCTAVE_VERSION'); +isoct=jsonopt('IsOctave',0,varargin{:}); for e=1:len if(isoct) val=regexprep(item(e,:),'\\','\\'); @@ -223,7 +226,7 @@ for e=1:len val=regexprep(val,'^"','\\"'); end if(len==1) - obj=['"' name '": ' '"',val,'"']; + obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"']; if(isempty(name)) obj=['"',val,'"']; end txt=sprintf('%s%s%s%s',txt,repmat(sprintf('\t'),1,level),obj); else @@ -249,7 +252,7 @@ if(length(size(item))>2 || issparse(item) || ~isreal(item) || jsonopt('ArrayToSt padding1,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') ); else txt=sprintf('%s"%s": {\n%s"_ArrayType_": "%s",\n%s"_ArraySize_": %s,\n',... - padding1,name,padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') ); + padding1,checkname(name,varargin{:}),padding0,class(item),padding0,regexprep(mat2str(size(item)),'\s+',',') ); end else if(isempty(name)) @@ -257,9 +260,9 @@ else else if(numel(item)==1 && jsonopt('NoRowBracket',1,varargin{:})==1) numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']',''); - txt=sprintf('%s"%s": %s',padding1,name,numtxt); + txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt); else - txt=sprintf('%s"%s": %s',padding1,name,matdata2json(item,level+1,varargin{:})); + txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),matdata2json(item,level+1,varargin{:})); end end return; @@ -340,3 +343,30 @@ opt=varargin{1}; if(isstruct(opt) && isfield(opt,key)) val=getfield(opt,key); end +%%------------------------------------------------------------------------- +function newname=checkname(name,varargin) +isunpack=jsonopt('UnpackHex',1,varargin{:}); +newname=name; +if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once'))) + return +end +if(isunpack) + isoct=jsonopt('IsOctave',0,varargin{:}); + if(~isoct) + newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}'); + else + pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start'); + pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end'); + if(isempty(pos)) return; end + str0=name; + pos0=[0 pend(:)' length(name)]; + newname=''; + for i=1:length(pos) + newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))]; + end + if(pos(end)~=length(name)) + newname=[newname str0(pos0(end-1)+1:pos0(end))]; + end + end +end +