|
164 | 164 | schema % JSON Schema for validation (struct), set via .setschema(), retrieve via .getschema() |
165 | 165 | end |
166 | 166 | properties (Access = private) |
167 | | - flags % additional options, will be passed to jsonlab utility functions such as savejson/loadjson |
168 | | - currentpath % internal variable tracking the current path when lookup embedded data at current depth |
| 167 | + flags__ % additional options, will be passed to jsonlab utility functions such as savejson/loadjson |
| 168 | + currentpath__ % internal variable tracking the current path when lookup embedded data at current depth |
169 | 169 | end |
170 | 170 | methods |
171 | 171 |
|
172 | 172 | % constructor: initialize a jdict object |
173 | 173 | function obj = jdict(val, varargin) |
174 | | - obj.flags = struct('builtinjson', 0); |
| 174 | + obj.flags__ = struct('builtinjson', 0); |
175 | 175 | obj.attr = containers.Map(); |
176 | 176 | obj.schema = []; |
177 | | - obj.currentpath = char(36); |
| 177 | + obj.currentpath__ = char(36); |
178 | 178 | if (nargin >= 1) |
179 | 179 | if (~isempty(varargin)) |
180 | 180 | allflags = [varargin(1:2:end); varargin(2:2:end)]; |
181 | | - obj.flags = struct(allflags{:}); |
182 | | - if (isfield(obj.flags, 'attr')) |
183 | | - obj.attr = obj.flags.attr; |
| 181 | + obj.flags__ = struct(allflags{:}); |
| 182 | + if (isfield(obj.flags__, 'attr')) |
| 183 | + obj.attr = obj.flags__.attr; |
184 | 184 | end |
185 | | - if (isfield(obj.flags, 'schema')) |
186 | | - obj.schema = obj.flags.schema; |
| 185 | + if (isfield(obj.flags__, 'schema')) |
| 186 | + obj.schema = obj.flags__.schema; |
187 | 187 | end |
188 | 188 | end |
189 | 189 | if (ischar(val) && ~isempty(regexpi(val, '^https*://', 'once'))) |
|
198 | 198 | obj.data = val.data; |
199 | 199 | obj.attr = val.attr; |
200 | 200 | obj.schema = val.schema; |
201 | | - obj.currentpath = val.currentpath; |
202 | | - obj.flags = val.flags; |
| 201 | + obj.currentpath__ = val.currentpath__; |
| 202 | + obj.flags__ = val.flags__; |
203 | 203 | else |
204 | 204 | obj.data = val; |
205 | 205 | end |
|
225 | 225 | % handle {} indexing for attributes |
226 | 226 | if (oplen == 1 && strcmp(idxkey(1).type, '{}')) |
227 | 227 | if (iscell(idxkey(1).subs) && length(idxkey(1).subs) == 1 && ischar(idxkey(1).subs{1})) |
228 | | - varargout{1} = obj.getattr(obj.currentpath, idxkey(1).subs{1}); |
| 228 | + varargout{1} = obj.getattr(obj.currentpath__, idxkey(1).subs{1}); |
229 | 229 | return |
230 | 230 | end |
231 | 231 | end |
232 | 232 |
|
233 | 233 | val = obj.data; |
234 | | - trackpath = obj.currentpath; |
| 234 | + trackpath = obj.currentpath__; |
235 | 235 |
|
236 | 236 | if (oplen == 1 && strcmp(idxkey(1).type, '()') && isempty(idxkey(1).subs)) |
237 | 237 | varargout{1} = val; |
|
254 | 254 |
|
255 | 255 | if (strcmp(idx.type, '.') && isnumeric(idx.subs)) |
256 | 256 | val = val(idx.subs); |
257 | | - elseif ((strcmp(idx.type, '()') || strcmp(idx.type, '.')) && ischar(idx.subs) && ismember(idx.subs, {'tojson', 'fromjson', 'v', 'isKey', 'keys', 'len', 'size', 'setattr', 'getattr', 'setschema', 'getschema', 'validate', 'attr2schema'}) && i < oplen) |
| 257 | + elseif ((strcmp(idx.type, '()') || strcmp(idx.type, '.')) && ischar(idx.subs) && ismember(idx.subs, {'tojson', 'fromjson', 'v', 'isKey', 'keys', 'len', 'size', 'setattr', 'getattr', 'setschema', 'getschema', 'validate', 'attr2schema'}) && i < oplen && strcmp(idxkey(i + 1).type, '()')) |
258 | 258 | if (strcmp(idx.subs, 'v')) |
259 | 259 | if (iscell(val) && strcmp(idxkey(i + 1).type, '()')) |
260 | 260 | idxkey(i + 1).type = '{}'; |
|
263 | 263 | tempobj = jdict(val); |
264 | 264 | tempobj.attr = obj.attr; |
265 | 265 | tempobj.schema = obj.schema; |
266 | | - tempobj.currentpath = trackpath; |
| 266 | + tempobj.currentpath__ = trackpath; |
267 | 267 | val = v(tempobj, idxkey(i + 1)); |
268 | 268 | elseif (isa(val, 'jdict')) |
269 | 269 | val = val.data; |
|
272 | 272 | tempobj = jdict(val); |
273 | 273 | tempobj.attr = obj.attr; |
274 | 274 | tempobj.schema = obj.schema; |
275 | | - tempobj.currentpath = trackpath; |
| 275 | + tempobj.currentpath__ = trackpath; |
276 | 276 | if (exist('OCTAVE_VERSION', 'builtin') ~= 0 && regexp(OCTAVE_VERSION, '^5\.')) |
277 | 277 | val = membercall_(tempobj, idx.subs, idxkey(i + 1).subs{:}); |
278 | 278 | else |
|
292 | 292 | tempobj = jdict(val); |
293 | 293 | tempobj.attr = obj.attr; |
294 | 294 | tempobj.schema = obj.schema; |
295 | | - tempobj.currentpath = trackpath; |
| 295 | + tempobj.currentpath__ = trackpath; |
296 | 296 | val = tempobj; |
297 | 297 | end |
298 | | - elseif (strcmp(idx.type, '.') && ischar(idx.subs) && strcmp(idx.subs, 'v') && oplen == 1) |
299 | | - i = i + 1; |
300 | | - continue |
301 | 298 | elseif ((strcmp(idx.type, '.') && ischar(idx.subs)) || (iscell(idx.subs) && ~isempty(idx.subs{1}))) |
302 | 299 | onekey = idx.subs; |
303 | 300 | if (iscell(onekey)) |
|
323 | 320 | newobj = jdict(val); |
324 | 321 | newobj.attr = obj.attr; |
325 | 322 | newobj.schema = obj.schema; |
326 | | - newobj.currentpath = trackpath; |
| 323 | + newobj.currentpath__ = trackpath; |
327 | 324 | val = newobj; |
328 | 325 | i = i + 2; |
329 | 326 | continue |
|
384 | 381 | end |
385 | 382 | end |
386 | 383 | newobj.schema = obj.schema; |
387 | | - newobj.currentpath = char(36); |
| 384 | + newobj.currentpath__ = char(36); |
388 | 385 | val = newobj; |
389 | 386 | end |
390 | 387 | varargout{1} = val; |
|
401 | 398 | if (iscell(idxkey(1).subs) && ~isempty(idxkey(1).subs)) |
402 | 399 | attrn = idxkey(1).subs{1}; |
403 | 400 | if (ischar(attrn)) |
404 | | - obj.setattr(obj.currentpath, attrn, otherobj); |
| 401 | + obj.setattr(obj.currentpath__, attrn, otherobj); |
405 | 402 | return |
406 | 403 | end |
407 | 404 | end |
|
413 | 410 | attrn = idxkey(oplen).subs{1}; |
414 | 411 | if (ischar(attrn)) |
415 | 412 | % Build the path by navigating through keys |
416 | | - temppath = obj.currentpath; |
| 413 | + temppath = obj.currentpath__; |
417 | 414 | for i = 1:oplen - 1 |
418 | 415 | idx = idxkey(i); |
419 | 416 | if (strcmp(idx.type, '.') || strcmp(idx.type, '()')) |
|
445 | 442 | if (strcmp(idxkey(oplen - 1).type, '.') && ischar(idxkey(oplen - 1).subs)) |
446 | 443 | dimname = idxkey(oplen - 1).subs; |
447 | 444 | % build path to the data |
448 | | - temppath = obj.currentpath; |
| 445 | + temppath = obj.currentpath__; |
449 | 446 | for i = 1:oplen - 2 |
450 | 447 | idx = idxkey(i); |
451 | 448 | if (strcmp(idx.type, '.') || strcmp(idx.type, '()')) |
|
503 | 500 | for i = 1:oplen |
504 | 501 | idx = idxkey(i); |
505 | 502 | if (strcmp(idx.type, '.')) |
506 | | - if (ischar(idx.subs) && strcmp(idx.subs, 'v')) |
| 503 | + if (ischar(idx.subs) && strcmp(idx.subs, 'v') && i < oplen && strcmp(idxkey(i + 1).type, '()')) |
507 | 504 | opcell{i + 1} = opcell{i}; |
508 | 505 | if (i < oplen && iscell(opcell{i})) |
509 | 506 | idxkey(i + 1).type = '{}'; |
|
563 | 560 | idx.type = '()'; |
564 | 561 | end |
565 | 562 |
|
566 | | - if (ischar(idx.subs) && strcmp(idx.subs, 'v')) |
| 563 | + if (ischar(idx.subs) && strcmp(idx.subs, 'v') && i < oplen && ismember(idxkey(i + 1).type, {'()', '{}'})) |
567 | 564 | opcell{i} = opcell{i + 1}; |
568 | 565 | continue |
569 | 566 | end |
|
692 | 689 | % internal: call member functions or external functions |
693 | 690 | function varargout = call_(obj, func, varargin) |
694 | 691 | % interface to external functions and dependencies |
695 | | - if (~obj.flags.builtinjson) |
| 692 | + if (~obj.flags__.builtinjson) |
696 | 693 | if (~exist('loadjson', 'file')) |
697 | 694 | error('you must first install jsonlab (https://github.com/NeuroJSON/jsonlab) or set "BuildinJSON" flag to 1'); |
698 | 695 | end |
|
718 | 715 | if (nargin == 3) |
719 | 716 | attrvalue = attrname; |
720 | 717 | attrname = jsonpath; |
721 | | - jsonpath = obj.currentpath; |
| 718 | + jsonpath = obj.currentpath__; |
722 | 719 | end |
723 | 720 | if (~isKey(obj.attr, jsonpath)) |
724 | 721 | obj.attr(jsonpath) = containers.Map(); |
|
733 | 730 | function val = getattr(obj, jsonpath, attrname) |
734 | 731 | val = []; |
735 | 732 | if (nargin == 1) |
736 | | - if (~isKey(obj.attr, obj.currentpath) && strcmp(obj.currentpath, char(36))) |
| 733 | + if (~isKey(obj.attr, obj.currentpath__) && strcmp(obj.currentpath__, char(36))) |
737 | 734 | val = keys(obj.attr); % list root-level attr keys |
738 | | - elseif (isKey(obj.attr, obj.currentpath)) |
739 | | - val = keys(obj.attr(obj.currentpath)); |
| 735 | + elseif (isKey(obj.attr, obj.currentpath__)) |
| 736 | + val = keys(obj.attr(obj.currentpath__)); |
740 | 737 | end |
741 | 738 | return |
742 | 739 | end |
743 | 740 | if (nargin == 2) |
744 | 741 | if (~isempty(jsonpath) && jsonpath(1) ~= char(36)) |
745 | 742 | attrname = jsonpath; |
746 | | - jsonpath = obj.currentpath; |
| 743 | + jsonpath = obj.currentpath__; |
747 | 744 | else |
748 | 745 | attrname = ''; |
749 | 746 | end |
|
829 | 826 | schema = struct; |
830 | 827 |
|
831 | 828 | % Add title/description at root |
832 | | - if strcmp(obj.currentpath, char(36)) |
| 829 | + if strcmp(obj.currentpath__, char(36)) |
833 | 830 | if ~isempty(schematitle) |
834 | 831 | schema.('title') = schematitle; |
835 | 832 | end |
|
840 | 837 |
|
841 | 838 | % Get all attribute paths |
842 | 839 | allpaths = keys(obj.attr); |
843 | | - basepath = obj.currentpath; |
| 840 | + basepath = obj.currentpath__; |
844 | 841 | baselen = length(basepath); |
845 | 842 |
|
846 | 843 | % Extract schema attributes at current path |
|
909 | 906 | % Recursively build child schema |
910 | 907 | tempobj = jdict(); |
911 | 908 | tempobj.attr = obj.attr; |
912 | | - tempobj.currentpath = childpath; |
| 909 | + tempobj.currentpath__ = childpath; |
913 | 910 | objproperties.(propname) = attr2schema(tempobj); |
914 | 911 | end |
915 | 912 | schema.('properties') = objproperties; |
|
919 | 916 | if ~isfield(schema, 'type') |
920 | 917 | if ~isempty(childpaths) |
921 | 918 | schema.('type') = 'object'; |
922 | | - elseif strcmp(obj.currentpath, char(36)) |
| 919 | + elseif strcmp(obj.currentpath__, char(36)) |
923 | 920 | schema.('type') = 'object'; |
924 | 921 | end |
925 | 922 | end |
|
0 commit comments