readdictionary
datatypes: d = readdictionary (filename)
datatypes: d = readdictionary (filename, Name, Value)
Read a dictionary from a JSON or an OpenDocument spreadsheet file.
d = readdictionary (filename) reads the JSON object in
the file filename, a character vector or a string scalar naming a
local file or an http or https address, and returns it as a
dictionary with string keys in the order of the file. The
value type is chosen from the values, all of them together:
double; integers beyond 2^53 give
uint64, or int64 when one is negative and all fit, and a
number with a fraction among them gives cell;
string; dates in ISO 8601 form without a time zone
(2024-01-01, 2024-01-01T10:00:00) or as
01-Jan-2024 give datetime, and times as
01:30:00 give duration; a timestamp with a zone mark
(Z, +02:00) stays text;
true and false give logical;
null is missing: NaN, a missing string or NaT
among the values above, the missing type when all are
null; among logical or 64-bit integer values, which have no
missing value, it gives cell;
cell: an
array becomes a column cell array of its elements, each typed alone, and
an object a dictionary read by these rules, {} an unconfigured
one.
d = readdictionary (filename, Name, Value)
specifies options with the following Name-Value paired arguments, whose
names and text values are matched in any case.
| Name | Value |
|---|---|
'FileType' | 'auto' (the default) tells the type
from the extension, .json, .ods or .fods;
'json' or 'ods' sets it. |
'ValueType' | 'auto' (the default) as above, or
one of 'cell', 'string', 'double',
'single', the integer types, 'logical',
'datetime' and 'duration'. Text is never read as a
number: it gives NaN, 0 or false; numbers give text under
'string', and true gives "true" or 1; arrays,
objects and null give the missing value of the type. Under
'datetime' text is read as dates, each keeping the zone it states:
Z gives UTC, an offset a fixed-offset zone, no mark no zone.
Under 'cell' every value is in a cell, objects read the same way. |
'DuplicateKeyRule' | 'auto' and
'makeUnique' rename a repeated key a as a_1,
a_2 and so on, skipping names in use; 'preserveLast'
keeps the first position with the last value; 'error' refuses. |
'DictionarySelector' | A JSON Pointer to the object to
read, as '/data/2', counting array elements from 0; '' is
the whole file. |
'DictionaryNodeName' | The name of the object to read:
the first key of that name, depth first. It cannot be given with
'DictionarySelector'. |
'DateLocale' | The locale of month names in dates, as
'de_DE'. |
'ParsingMode' | 'lenient' (the default) allows
comments, trailing commas and NaN, Inf and
Infinity; 'strict' refuses them. |
'AllowComments', 'AllowTrailingCommas',
'AllowInfAndNaN' Logical scalars allowing each form; each
overrides 'ParsingMode'. |
The top level, or the object selected, must be a JSON object. MATLAB’s
'ValueType', 'datetime' reads an ISO 8601 date as NaT;
here it reads it as the default does.
An OpenDocument spreadsheet, FileType 'ods', gives one
entry per sheet, the sheet name the key and the table or
timetable read by ods2struct the value, so that a dictionary
written by writedictionary comes back as written. A workbook
holding both tables and timetables gives cell values. Reading
ODS is an extension of this package; it takes no option but
'FileType'.
Remote locations other than http and https (Amazon S3,
Azure Blob Storage, HDFS), compressed files and 'WebOptions',
which MATLAB accepts, are not supported.
See also: dictionary, dictionary.writedictionary, ods2struct
Source Code: readdictionary
readdictionary reads the JSON object in a file as a dictionary with string keys, in the order of the file. The value type follows the values: here they are all numbers, so they are double.
f = [tempname() '.json'];
text = '{"Boston": 55, "Denver": 48, "Dallas": 75}'
text = {"Boston": 55, "Denver": 48, "Dallas": 75}
fid = fopen (f, 'w'); fputs (fid, text); fclose (fid); temps = readdictionary (f)
temps =
dictionary (string ⟼ double) with 3 entries:
"Boston" ⟼ 55
"Denver" ⟼ 48
"Dallas" ⟼ 75
delete (f);
Values of different kinds give cell values. An array becomes a column cell array and a nested object a dictionary of its own, so {} reaches into both; null is missing.
f = [tempname() '.json'];
text = ['{"id": 12345, "tags": ["new", "urgent"], ', ...
'"sender": {"name": "Ann", "id": 7}, "reply": null}']
text = {"id": 12345, "tags": ["new", "urgent"], "sender": {"name": "Ann", "id": 7}, "reply": null}
fid = fopen (f, 'w'); fputs (fid, text); fclose (fid); msg = readdictionary (f)
msg =
dictionary (string ⟼ cell) with 4 entries:
"id" ⟼ {[12345]}
"tags" ⟼ {2x1 cell}
"sender" ⟼ {[dictionary (string ⟼ cell) with 2 entries]}
"reply" ⟼ {[<missing>]}
msg{'tags'}
ans =
2x1 cell array
{["new" ]}
{["urgent"]}
sender = msg{'sender'}
sender =
dictionary (string ⟼ cell) with 2 entries:
"name" ⟼ {["Ann"]}
"id" ⟼ {[7]}
delete (f);
Text in ISO 8601 form becomes dates, and hh:mm:ss durations. A timestamp marked with a time zone stays text, unless dates are asked for with 'ValueType', when each keeps the zone it states.
f = [tempname() '.json'];
text = '{"start": "2024-03-01", "end": "2024-03-15"}'
text = {"start": "2024-03-01", "end": "2024-03-15"}
fid = fopen (f, 'w'); fputs (fid, text); fclose (fid); dates = readdictionary (f)
dates =
dictionary (string ⟼ datetime) with 2 entries:
"start" ⟼ 2024-03-01
"end" ⟼ 2024-03-15
text = ['{"utc": "2024-03-01T10:00:00Z", ', ...
'"local": "2024-03-01T12:00:00+02:00"}']
text = {"utc": "2024-03-01T10:00:00Z", "local": "2024-03-01T12:00:00+02:00"}
fid = fopen (f, 'w'); fputs (fid, text); fclose (fid); asText = readdictionary (f)
asText =
dictionary (string ⟼ string) with 2 entries:
"utc" ⟼ "2024-03-01T10:00:00Z"
"local" ⟼ "2024-03-01T12:00:00+02:00"
asDates = readdictionary (f, 'ValueType', 'datetime')
asDates =
dictionary (string ⟼ datetime) with 2 entries:
"utc" ⟼ 2024-03-01T10:00:00Z
"local" ⟼ 2024-03-01T12:00:00+02:00
v = values (asDates, 'cell');
v{2}.TimeZone
ans = +02:00
delete (f);
'DictionarySelector' reads one object within the file by a JSON Pointer, counting array elements from 0, and 'DuplicateKeyRule' says what a repeated key becomes: renamed by default, or the last value kept.
f = [tempname() '.json'];
text = '{"site": {"a": 1, "a": 2, "b": 3}, "runs": [{"x": 10}, {"x": 20}]}'
text = {"site": {"a": 1, "a": 2, "b": 3}, "runs": [{"x": 10}, {"x": 20}]}
fid = fopen (f, 'w'); fputs (fid, text); fclose (fid); readdictionary (f, 'DictionarySelector', '/site')
ans =
dictionary (string ⟼ double) with 3 entries:
"a" ⟼ 1
"a_1" ⟼ 2
"b" ⟼ 3
readdictionary (f, 'DictionarySelector', '/site', ...
'DuplicateKeyRule', 'preserveLast')
ans =
dictionary (string ⟼ double) with 2 entries:
"a" ⟼ 2
"b" ⟼ 3
readdictionary (f, 'DictionarySelector', '/runs/1')
ans =
dictionary (string ⟼ double) with 1 entry:
"x" ⟼ 20
delete (f);
An OpenDocument spreadsheet gives one entry per sheet, the sheet name the key and its table or timetable the value, so a dictionary of tables written by writedictionary comes back as it was.
sales = dictionary (string ({'North', 'South 2024'}), ...
{table([10; 12], {'pens'; 'ink'}), ...
table(7, {'tape'})})
sales =
dictionary (string ⟼ cell) with 2 entries:
"North" ⟼ {2x2 table}
"South 2024" ⟼ {1x2 table}
f = [tempname() '.ods']; writedictionary (sales, f); back = readdictionary (f)
back =
dictionary (string ⟼ table) with 2 entries:
"North" ⟼ 2x2 table
"South 2024" ⟼ 1x2 table
back('South 2024')
ans =
1x2 table
Var1 Var2
____ ________
7 {'tape'}
delete (f);