From 4f2edebee39fb750a597557bd31d4d2fc5494241 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Mon, 19 Feb 2024 22:24:44 -0500 Subject: [PATCH] [feat] support .. jsonpath operator for deep scan --- getfromjsonpath.m | 109 ++++++++++++++++++++++++++++++++++++++-------- loadjd.m | 28 ++++++++++-- 2 files changed, 114 insertions(+), 23 deletions(-) diff --git a/getfromjsonpath.m b/getfromjsonpath.m index 9a1d84f..128c5c1 100644 --- a/getfromjsonpath.m +++ b/getfromjsonpath.m @@ -23,28 +23,99 @@ % obj = root; -jsonpath = regexprep(jsonpath, '([^.])(\[\d+\])', '$1.$2'); -[pat, paths] = regexp(jsonpath, '\.*([^\s\.]+)\.*', 'match', 'tokens'); +jsonpath = regexprep(jsonpath, '([^.])(\[[0-9:]+\])', '$1.$2'); +[pat, paths] = regexp(jsonpath, '(\.{0,2}[^\s\.]+)', 'match', 'tokens'); if (~isempty(pat) && ~isempty(paths)) for i = 1:length(paths) - if (strcmp(paths{i}{1}, '$')) - continue - elseif (regexp(paths{i}{1}, '$\d+')) - obj = obj(str2double(paths{i}{1}(2:end)) + 1); - elseif (regexp(paths{i}{1}, '^\[\d+\]$')) - if (iscell(obj)) - obj = obj{str2double(paths{i}{1}(2:end - 1)) + 1}; - else - obj = obj(str2double(paths{i}{1}(2:end - 1)) + 1); - end - elseif (isstruct(obj)) - obj = obj.(encodevarname(paths{i}{1})); - elseif (isa(obj, 'containers.Map')) - obj = obj(paths{i}{1}); - elseif (isa(obj, 'table')) - obj = obj(:, paths{i}{1}); + [obj, isfound] = getonelevel(obj, paths{i}{1}); + if (~isfound) + return + end + end +end + +%% scan function + +function [obj, isfound] = getonelevel(input, pathname) + +deepscan = ~isempty(regexp(pathname, '^\.\.', 'once')); + +pathname = regexprep(pathname, '^\.+', ''); + +if (strcmp(pathname, '$')) + obj = input; +elseif (regexp(pathname, '$\d+')) + obj = input(str2double(pathname(2:end)) + 1); +elseif (regexp(pathname, '^\[[0-9:]+\]$')) + arraystr = pathname(2:end - 1); + if (find(arraystr == ':')) + [arraystr, arrayrange] = regexp(arraystr, '(\d*):(\d*)', 'match', 'tokens'); + arrayrange = arrayrange{1}; + if (~isempty(arrayrange{1})) + arrayrange{1} = str2double(arrayrange{1}) + 1; + else + arrayrange{1} = 1; + end + if (~isempty(arrayrange{2})) + arrayrange{2} = str2double(arrayrange{2}) + 1; else - error('json path segment (%d) "%s" can not be found in the input object\n', i, paths{i}{1}); + arrayrange{2} = length(input); end + else + arrayrange = str2double(arraystr) + 1; + arrayrange = {arrayrange, arrayrange}; end + if (iscell(input)) + obj = {input{arrayrange{1}:arrayrange{2}}}; + else + obj = input(arrayrange{1}:arrayrange{2}); + end +elseif (isstruct(input)) + stpath = encodevarname(pathname); + if (deepscan) + if (isfield(input, stpath)) + obj = {input.(stpath)}; + end + items = fieldnames(input); + for idx = 1:length(items) + [val, isfound] = getonelevel(input.(items{idx}), ['..' pathname]); + if (isfound) + if (~exist('obj', 'var')) + obj = {}; + end + obj = [obj{:}, val]; + end + end + else + obj = input.(stpath); + end +elseif (isa(input, 'containers.Map')) + if (deepscan) + if (isKey(input, pathname)) + obj = {input(pathname)}; + end + items = keys(input); + for idx = 1:length(items) + [val, isfound] = getonelevel(input(items{idx}), ['..' pathname]); + if (isfound) + if (~exist('obj', 'var')) + obj = {}; + end + obj = [obj{:}, val]; + end + end + else + obj = input(pathname); + end +elseif (isa(input, 'table')) + obj = input(:, pathname); +elseif (~deepscan) + error('json path segment "%s" can not be found in the input object\n', pathname); +end + +if (~exist('obj', 'var')) + isfound = false; + obj = []; +elseif (nargout > 1) + isfound = true; end diff --git a/loadjd.m b/loadjd.m index b89b4c5..3cf13d4 100644 --- a/loadjd.m +++ b/loadjd.m @@ -16,7 +16,11 @@ % *.bjd,.bnii,.jdb,.bmsh,.bnirs,.pmat: binary JData (BJData) files, see https://neurojson.org/bjdata/draft2 % *.ubj: UBJSON-encoded files, see http://ubjson.org % *.msgpack: MessagePack-encoded files, see http://msgpack.org -% *.h5,.hdf5,.snirf: HDF5 files, see https://www.hdfgroup.org/ +% *.h5,.hdf5,.snirf,.nwb: HDF5 files, see https://www.hdfgroup.org/ +% *.nii,.nii.gz: NIfTI files, need http://github.com/NeuroJSON/jnifty +% *.tsv,.tsv.gz,.csv,.csv.gz: TSV/CSV files, need http://github.com/NeuroJSON/jbids +% *.bval,.bvec: EEG .bval and .bvec files +% *.mat: MATLAB/Octave .mat files % options: (optional) for JSON/JData files, these are optional 'param',value pairs % supported by loadjson.m; for BJData/UBJSON/MessagePack files, these are % options supported by loadbj.m; for HDF5 files, these are options @@ -45,17 +49,33 @@ if (regexpi(filename, '\.json$|\.jnii$|\.jdt$|\.jdat$|\.jmsh$|\.jnirs|\.jbids$')) [varargout{1:nargout}] = loadjson(filename, varargin{:}); -elseif (regexpi(filename, '\.bjd$|\.bnii$|\.jdb$|\.jbat$|\.bmsh$|\.bnirs$|\.pmat')) +elseif (regexpi(filename, '\.bjd$|\.bnii$|\.jdb$|\.jbat$|\.bmsh$|\.bnirs$|\.pmat$')) [varargout{1:nargout}] = loadbj(filename, varargin{:}); elseif (regexpi(filename, '\.ubj$')) [varargout{1:nargout}] = loadubjson(filename, varargin{:}); elseif (regexpi(filename, '\.msgpack$')) [varargout{1:nargout}] = loadmsgpack(filename, varargin{:}); -elseif (regexpi(filename, '\.h5$|\.hdf5$|\.snirf$')) +elseif (regexpi(filename, '\.h5$|\.hdf5$|\.snirf$|\.nwb$')) if (~exist('loadh5', 'file')) error('you must first install EasyH5 from http://github.com/NeuroJSON/easyh5/'); end [varargout{1:nargout}] = loadh5(filename, varargin{:}); +elseif (regexpi(filename, '\.nii$|\.nii\.gz$')) + if (~exist('loadnifti', 'file')) + error('you must first install JNIFTY toolbox from http://github.com/NeuroJSON/jnifty/'); + end + [varargout{1:nargout}] = loadnifti(filename, varargin{:}); +elseif (regexpi(filename, '\.tsv$|\.tsv\.gz$|\.csv$|\.csv\.gz$')) + if (~exist('loadbidstsv', 'file')) + error('you must first install JBIDS toolbox from http://github.com/NeuroJSON/jbids/'); + end + delim = sprintf('\t'); + if (regexpi(filename, '\.csv')) + delim = ','; + end + [varargout{1:nargout}] = loadbidstsv(filename, delim); +elseif (regexpi(filename, '\.mat$|\.bvec$|\.bval$')) + [varargout{1:nargout}] = load(filename, varargin{:}); else - error('file suffix must be one of .json,.jnii,.jdt,.jmsh,.jnirs,.jbids,.bjd,.bnii,.jdb,.bmsh,.bnirs,.ubj,.msgpack,.h5,.hdf5,.snirf,.pmat'); + error('file suffix must be one of .json,.jnii,.jdt,.jmsh,.jnirs,.jbids,.bjd,.bnii,.jdb,.bmsh,.bnirs,.ubj,.msgpack,.h5,.hdf5,.snirf,.pmat,.nwb,.nii,.nii.gz,.tsv,.tsv.gz,.csv,.csv.gz,.mat,.bvec,.bval'); end