jdict jdict

Universal Dictionary Interface for MATLAB/Octave

A powerful, xarray-inspired data structure that combines the flexibility of Python dictionaries with MATLAB's numerical computing power. Now with JSON Schema validation!

🚀 Unified Access

Works seamlessly with structs, containers.Map, and dictionaries

🎯 JSONPath Support

Query nested data with powerful JSONPath expressions

🔬 Dimension Labels

xarray-like dimension indexing for scientific data

⚡ Attribute Storage

Attach metadata to any level of your data hierarchy

✅ Schema ValidationNew

Validate data against JSON Schema with full constraint support

🛡️ Validated AssignmentNew

Use <= operator for schema-checked assignments

Scroll to explore

Getting Started

Simple, Intuitive Syntax

Access nested data structures with clean, readable syntax. No more deep struct navigation!

% Create a complex nested structure
data = struct('experiments', ...
    struct('trial1', rand(100, 64), 'metadata', ...
        struct('date', '2025-01-01', 'subject', 'P001')));

jd = jdict(data);

% Clean navigation
subject = jd.('experiments').('metadata').('subject')()

% Or use JSONPath for deep queries
subject = jd.('$.experiments.metadata.subject')()

Metadata Management

Attach Attributes Anywhere

Store metadata like dimension names, units, and descriptions alongside your data. Perfect for scientific datasets!

% Create EEG data
eeg_data = rand(1000, 64, 50);  % time x channels x trials
jd = jdict(eeg_data);

% Attach metadata using curly braces (MATLAB)
jd{'dims'} = {'time', 'channels', 'trials'};
jd{'units'} = 'microvolts';
jd{'sampling_rate'} = 1000;

% Read attributes
dims = jd{'dims'}          % → {'time', 'channels', 'trials'}
units = jd{'units'}        % → 'microvolts'

xarray-Inspired

Dimension-Based Selection

Select data using dimension names instead of numeric indices. Make your code self-documenting!

% Setup multidimensional data
jd = jdict(rand(1000, 64, 50));
jd{'dims'} = {'time', 'channels', 'trials'};

% Select by dimension name - so much clearer!
first_100 = jd.time(1:100);           % First 100 timepoints
channel_5 = jd.channels(5);          % Just channel 5
subset = jd.time(1:500).trials(1:10);  % Chain selections!

% No more confusing: data(1:100, :, :) vs data(:, 5, :) ✨

Advanced Features

Smart Struct Array Handling

Build struct arrays incrementally with field-by-field or direct struct assignment. Perfect for tabular data!

% Create empty struct array with predefined fields
person = jdict(struct('name', {}, 'age', {}, 'gender', {}));

% Direct struct assignment
person.v(1) = struct('name', 'Alice', 'age', 30, 'gender', 'F');
person.v(2) = struct('name', 'Bob', 'age', 25, 'gender', 'M');

% Or field-by-field assignment
person.v(3).name = 'Charlie';
person.v(3).age = 35;
person.v(3).gender = 'M';

person.tojson()  % → [{"name":"Alice",...},{"name":"Bob",...},...]

Powerful Queries

JSONPath Deep Search

Use JSONPath expressions to query complex nested structures. Find data anywhere in your hierarchy!

% Load complex REST API data
jd = jdict('https://api.example.com/data.json');

% Deep search with '..' operator
all_names = jd.('$..name')();      % Find all 'name' fields
all_ids = jd.('$..id')();          % Find all 'id' fields

% Array indexing in path
first = jd.('$.results[0].data')();

% Combine with attribute access
jd.('$.results[0]'){'processed'} = true;

Data Integrity

JSON Schema ValidationNew

Define and validate your data against JSON Schema. Catch errors early with comprehensive constraint checking!

% Create data and define schema
jd = jdict(struct('name', 'John', 'age', 30));

schema = struct('type', 'object', ...
    'properties', struct( ...
        'name', struct('type', 'string', 'minLength', 1), ...
        'age', struct('type', 'integer', 'minimum', 0, 'maximum', 150)), ...
    'required', {{'name', 'age'}});

% Set and validate
jd.setschema(schema);
errors = jd.validate();      % → {} (empty = valid!)

% Get schema back as JSON
jd.getschema('json')           % → '{"type":"object",...}'

% Validate subkeys independently
jd.name.validate()            % → {} (name is valid)
jd.age.validate()             % → {} (age is valid)

Inline Schema Definition

Schema via AttributesNew

Define schema constraints directly as attributes using :keyword syntax. Then export to a full JSON Schema with attr2schema()!

% Create data structure
jd = jdict(struct('name', 'test', 'count', 5));

% Define schema inline using :keyword attributes
jd.('name').setattr(':type', 'string');
jd.('name').setattr(':minLength', 1);
jd.('count').setattr(':type', 'integer');
jd.('count').setattr(':minimum', 0);
jd.('count').setattr(':maximum', 100);

% Export to JSON Schema
schema = jd.attr2schema('title', 'My Data Schema');

% Use the generated schema for validation
jd.setschema(schema);
errors = jd.validate();      % → {}

% Supports all JSON Schema keywords: enum, pattern, format, etc.
jd.('status').setattr(':enum', {'active', 'inactive'});

Safe Data Mutation

Validated Assignment with <=New

Use the <= operator for schema-validated assignments. Invalid values throw errors before corrupting your data!

% Setup data with schema
jd = jdict(struct('name', {}, 'age', {}, 'status', {}));
jd.setschema(struct('type', 'object', 'properties', struct( ...
    'name', struct('type', 'string'), ...
    'age', struct('type', 'integer', 'minimum', 0, 'maximum', 150), ...
    'status', struct('enum', {{'active', 'inactive'}}))));

% Valid assignments pass silently
jd.name <= 'Jane';           % ✓ OK
jd.age <= 25;                % ✓ OK
jd.status <= 'inactive';    % ✓ OK

% Invalid assignments throw errors!
jd.age <= -5;                % ✗ Error: minimum violation
jd.age <= 200;               % ✗ Error: maximum violation
jd.status <= 'unknown';     % ✗ Error: not in enum
jd.name <= 123;              % ✗ Error: type mismatch

Ready to Use

Get Started with jdict

Part of the JSONLab toolbox — one of MATLAB's most popular 3rd-party JSON parsers.

Installation

% Download JSONLab from GitHub
git clone https://github.com/NeuroJSON/jsonlab.git

% Add to MATLAB path
addpath('/path/to/jsonlab');

Key Methods

jd.('key') — Navigate
jd{'attr'} — Get/set attributes
jd.dim(idx) — Select by dimension
jd.tojson() — Export to JSON
jd.setschema(s) — Set JSON Schema
jd.validate() — Validate data
jd.attr2schema() — Export schema
jd.key <= val — Validated assign

Created by Qianqian Fang • Part of the NeuroJSON Project

Powered by Habitat