Categories &

Functions List

Function Reference: 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:

  • numbers give 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;
  • text gives 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;
  • any other mixture, an array, or an object gives 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.

NameValue
'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);