diff --git a/jsonpath.m b/jsonpath.m index eb3e771..0c9875a 100644 --- a/jsonpath.m +++ b/jsonpath.m @@ -1,6 +1,6 @@ -function obj = jsonpath(root, jsonpath) +function obj = jsonpath(root, jpath) % -% obj=jsonpath(root, jsonpath) +% obj=jsonpath(root, jpath) % % Query and retrieve elements from matlab data structures using JSONPath % @@ -8,7 +8,7 @@ % % input: % root: a matlab data structure like an array, cell, struct, etc -% jsonpath: a string in the format of JSONPath, see loadjson help +% jpath: a string in the format of JSONPath, see loadjson help % % output: % obj: if the specified element exist, obj returns the result @@ -23,9 +23,13 @@ % obj = root; -jsonpath = regexprep(jsonpath, '([^.\]])(\[[-0-9:\*]+\])', '$1.$2'); -jsonpath = regexprep(jsonpath, '\[[''"]*([^\]''"]+)[''"]*\]', '.[$1]'); -[pat, paths] = regexp(jsonpath, '(\.{0,2}[^\.]+)', 'match', 'tokens'); +jpath = regexprep(jpath, '([^.\]])(\[[-0-9:\*]+\])', '$1.$2'); +jpath = regexprep(jpath, '\[[''"]*([^\]''"]+)[''"]*\]', '.[$1]'); +jpath = regexprep(jpath, '\\\.', '_0x2E_'); +while(regexp(jpath, '(\[[''"]*[^\]''"]+)\.(?=[^\]''"]+[''"]*\])')) + jpath = regexprep(jpath, '(\[[''"]*[^\]''"]+)\.(?=[^\]''"]+[''"]*\])', '$1_0x2E_'); +end +[pat, paths] = regexp(jpath, '(\.{0,2}[^\.]+)', 'match', 'tokens'); if (~isempty(pat) && ~isempty(paths)) if (strcmp(paths{1}, '$')) paths(1) = []; @@ -139,6 +143,8 @@ for idx = 1:length(items) if (isa(input, 'containers.Map')) [val, isfound] = getonelevel(input(items{idx}), [paths{1:pathid - 1} {['..' pathname]}], pathid); + elseif (length(input) > 1) % struct array + [val, isfound] = getonelevel({input.(items{idx})}, [paths{1:pathid - 1} {['..' pathname]}], pathid); else [val, isfound] = getonelevel(input.(items{idx}), [paths{1:pathid - 1} {['..' pathname]}], pathid); end diff --git a/test/run_jsonlab_test.m b/test/run_jsonlab_test.m index 5e6a55f..2869add 100644 --- a/test/run_jsonlab_test.m +++ b/test/run_jsonlab_test.m @@ -382,14 +382,8 @@ function run_jsonlab_test(tests) test_jsonlab('jsonpath use [''*''] and ["*"]', @savejson, jsonpath(testdata, '$["book"][:-2][''author'']'), '["Yoda","Jinn"]', 'compact', 1); test_jsonlab('jsonpath use combinations', @savejson, jsonpath(testdata, '$..["book"][:-2].author[*][0]'), '["Yoda"]', 'compact', 1); - testdata = struct('book', struct(encodevarname('_title'), {'Minch', 'Qui-Gon', 'Ben'}, encodevarname(' author '), {'Yoda', 'Jinn', 'Kenobi'}), 'game', struct('title', 'Mario')); - test_jsonlab('jsonpath encoded field name in []', @savejson, jsonpath(testdata, '$..["book"][_title][*][0]'), '["Minch"]', 'compact', 1); - test_jsonlab('jsonpath encoded field name after .', @savejson, jsonpath(testdata, '$..["book"]._title[*][0]'), '["Minch"]', 'compact', 1); - test_jsonlab('jsonpath encoded field name after ..', @savejson, jsonpath(testdata, '$.._title'), '["Minch","Qui-Gon","Ben"]', 'compact', 1); - test_jsonlab('jsonpath encoded field name after .', @savejson, jsonpath(testdata, '$..["book"]['' author ''][*][1]'), '["Jinn"]', 'compact', 1); - if (exist('containers.Map')) - testdata = struct('book', containers.Map({'title', 'author'}, {{'Minch', 'Qui-Gon', 'Ben'}, {'Yoda', 'Jinn', 'Kenobi'}}), 'game', struct('title', 'Mario')); + testdata = loadjson(savejson('', testdata), 'usemap', 1); test_jsonlab('jsonpath use combinations', @savejson, jsonpath(testdata, '$..["book"].author[*][0]'), '["Yoda"]', 'compact', 1); end if (exist('istable')) @@ -397,6 +391,16 @@ function run_jsonlab_test(tests) test_jsonlab('jsonpath use combinations', @savejson, jsonpath(testdata, '$..["book"].author[*][0]'), '["Yoda"]', 'compact', 1); end + testdata = struct('book', struct(encodevarname('_title'), {'Minch', 'Qui-Gon', 'Ben'}, encodevarname(' author.last.name '), {'Yoda', 'Jinn', 'Kenobi'}), encodevarname('game.arcade'), struct('title', 'Mario')); + test_jsonlab('jsonpath encoded field name in []', @savejson, jsonpath(testdata, '$..["book"][_title][*][0]'), '["Minch"]', 'compact', 1); + test_jsonlab('jsonpath encoded field name after .', @savejson, jsonpath(testdata, '$..["book"]._title[*][0]'), '["Minch"]', 'compact', 1); + test_jsonlab('jsonpath encoded field name after ..', @savejson, jsonpath(testdata, '$.._title'), '["Minch","Qui-Gon","Ben"]', 'compact', 1); + test_jsonlab('jsonpath multiple encoded field name between quotes', @savejson, jsonpath(testdata, '$..["book"]['' author.last.name ''][*][1]'), '["Jinn"]', 'compact', 1); + test_jsonlab('jsonpath multiple encoded field name between []', @savejson, jsonpath(testdata, '$..["book"][ author.last.name ][*][1]'), '["Jinn"]', 'compact', 1); + test_jsonlab('jsonpath escape . using \.', @savejson, jsonpath(testdata, '$.game\.arcade'), '{"title":"Mario"}', 'compact', 1); + test_jsonlab('jsonpath escape . using []', @savejson, jsonpath(testdata, '$.[game.arcade]'), '{"title":"Mario"}', 'compact', 1); + test_jsonlab('jsonpath scan struct array', @savejson, jsonpath(testdata, '$.book[*]..author[*]'), '[]', 'compact', 1); + clear testdata; end