JSONLab 2.0 (codename: Magnus Prime)
What's New
Nine years in the making, JSONLab 2.0 (codename: Magnus Prime) has finally arrived!
JSONLab 2.0 is not just a MATLAB/Octave toolbox, but a reference library to the below two new data specifications:
- JData (language-independent data annotations) Draft 3: https://github.com/OpenJData/jdata/
- Binary JData (a portable interchange format for binary data) Draft 1: https://github.com/OpenJData/bjdata/
Numerous updates have been added in this milestone release since its previous
version v1.9.8 in Oct. 2019. A list of the major changes are summarized below
(with key features marked by *), including the support to _ArrayShape_
to
efficiently encode special matrices, the addition of jsave/jload
to save
and restore variables in MATLAB/Octave like the save/load
commands
(experimental), and the associated Python modules (jdata
and bjdata
):
- 2020-06-13 [81feef3] skip no-op markers, update documentation
- 2020-06-13 [4904155] jload load data to struct, test if loadbj input is buffer, update error msg
- 2020-06-12 [c334799] change default workspace to caller for jload and jsave
- 2020-06-10 [c883546] fix keeptype single integer bug
- 2020-06-09*[ ] created
jdata
andbjdata
python modules to share data with MATLAB - 2020-06-08*[cbde607] add savebj and loadbj to dedicate to loading and saving bjdata
- 2020-06-08*[e2451e1] add unit testing script, fix issues found in the testing unit
- 2020-06-06 [a44015f] accelerate fast_match_bracket, drop unicode2native for speed
- 2020-06-06 [eefccf3] call jsonencode/decode in jsave/jload, parse embedded jdata struct
- 2020-06-05 [9434103] support Toeplitz matrices, use case-insensitive comparison
- 2020-06-04 [3119ce4] jdatadecode now handles ArrayOrder
- 2020-06-04 [89b844c] remove forced root name, update internal test results
- 2020-06-02*[15ca7ae] add keeptype option to jsave and saveubjson
- 2020-06-02 [7f2cbc4] make jsave and jload work on octave
- 2020-06-01*[8829d6b] apply data compression to strings, new datatype char
- 2020-06-01 [270cbf6] fix loadmsgpack ND array issue
- 2020-06-01*[919f502] add jsave and jload for portable data sharing
- 2020-05-31 [df3a4fa] debug arrayshape related changes and test all demo scripts
- 2020-05-31*[fc0b285] adding support to ArrayShape to record special matrices
- 2020-05-15*[d88d454] jsonlab is compatible with matlab R2008
- 2020-05-13 [86efe89] flag to prevent embedding ND array size specifier
- 2020-05-07 [a189a50] use more robust integer type testing
- 2020-05-06*[82f5249] saveubjson now implments BJData spec Draft1,https://github.com/fangq/bjdata
- 2020-05-03 [34bca22] add prj file to compile a matlab package, close #60
- 2020-05-03 [82dfdcc] handle empty array in loadmsgpack, fix #63, patch by stfnp
- 2020-03-08 [7499bd8] Merge pull request #61 from j2L4e/patch-1
- 2020-02-09*[6984111] add UseMap option to avoid key name conversion
- 2019-11-16 [e46221a] if ArraySize has a single length, treat as a row vector
- 2019-11-01 [f2bfb65] fix a uint8 upper bound bug
- 2019-10-24 [cc4491d] avoid escaping base64 str, avoid double processing preencoded arrayzipdata
- 2019-10-24 [4dc76ef] make example script compatible with matlab R2010
- 2019-10-24 [ad8be26] disable underscore escaping in octave,update all tests and outputs
- 2019-10-24 [d4275c6] reduce jsonopt calls to speed up encoding and decoding
- 2019-10-23 [82c9e91] fix invalid jdatadecode example
- 2019-10-23 [398539d] reoptimize for speed
- 2019-10-22*[650b5ec] enable jdataencode in savejson and saveubjson
Please note that JSONLab v2.0 is now compliant with JData Spec Draft 3; in
comparison, v1.9.8 is compatible with Draft 2; v1.9 and previous releases are
compatible with Draft 1. JSONLab v2.0 can read all data files generated by
v1.9.8, but v1.9.8 can not read the new UBJSON markers introduced in v2.0.
The newly introduced jsave/jload
functions are in the experimental stage.
They generate .jamm
files which are renamed binary-JData/UBJSON files;
they can be 50% smaller than .mat
files if using jsave(...,'compression','lzma')
and can be readily opened among a long list of programming environments
such as Python, JavaScript and Go.
The saveubjson/loadubjson
functions added support to the Binary JData specification (BJData)
v1 Draft-1 (https://github.com/fangq/bjdata) and are now renamed as savebj/loadbj
(saveubjson/loadubjson
are kept for compatibility purposes as aliases to the new
functions). The BJData spec is largely compatible with UBJSON spec Draft 12, with the
following differences (we are working with the UBJSON maintainer to merge
these two specifications):
- BJData adds 4 new numeric data types:
uint16 [u]
,uint32 [m]
,uint64 [M]
andfloat16 [h]
('''new in JSONLab v2.0''') - BJData supports an optimized ND array container (supported in JSONLab since 2013)
- BJData does not convert
NaN/Inf/-Inf
tonull
(supported in JSONLab since 2013)
To avoid using the new type markers, one should attach 'UBJSON',1
in the savebj
command as
savebj('',data,'FileName','myfile.bjd','UBJSON',1);
To read data files generated by JSONLab v1.9 or older versions, you need to attach
option 'FormatVersion', 1.9
in all the loadjson/savejson
function calls.
To convert an older file (JSON/UBJSON) to the new format, you should run
data=loadjson('my_old_data_file.json','FormatVersion',1.9)
savejson('',data,'FileName','new_file.json')
You are strongly encouraged to convert all pre-v1.9.8 generated data files using the new
format.
Introduction
JSONLab is a free and open-source JSON/UBJSON/MessagePack encoder and
decoder written in the native MATLAB language. It can be used to convert a MATLAB
data structure (array, struct, cell, struct array, cell array, and objects) into
JSON/UBJSON/MessagePack formatted strings and files, or to parse a
JSON/UBJSON/MessagePack file into MATLAB data structure. JSONLab supports both
MATLAB and GNU Octave (a free MATLAB clone).
JSON (JavaScript Object Notation) is a highly portable, human-readable and "fat-free" text format
to represent complex and hierarchical data, widely used for data-exchange in applications.
UBJSON (Universal Binary JSON) is a binary JSON format,
specifically designed to specifically address the limitations of JSON, permitting
efficient storage of binary data with strongly typed data records, resulting in smaller
file sizes and fast encoding and decoding. MessagePack is another binary
JSON-like data format widely used in data exchange in web/native applications.
It is slightly more compact than UBJSON, but is not directly readable compared
to UBJSON.
We envision that both JSON and its binary counterparts will play important
rules not only for light-weight data storage, but also for storage and interchange
of scientific data. It has both the flexibility and generality as in other general-purpose
file specifications, such as HDF5 but has significantly reduced complexity
and excellent readability.
Towards this goal, we have developed the JData Specification (http://github.com/fangq/jdata)
to standardize serializations of complex scientific data structures, such as
N-D arrays, sparse/complex-valued arrays, trees, maps, tables and graphs using
JSON/binary JSON constructs. The text and binary formatted JData files are
syntactically compatible with JSON/UBJSON formats, and can be readily parsed
using existing JSON and UBJSON parsers. JSONLab is not just a parser and writer
of JSON/UBJSON data files, but one that systematically converts complex scientific
data structures into human-readable and universally supported JSON forms using the
standardized JData data annotations.
Installation
The installation of JSONLab is no different from installing any other
MATLAB toolbox. You only need to download/unzip the JSONLab package
to a folder, and add the folder's path to MATLAB/Octave's path list
by using the following command:
addpath('/path/to/jsonlab');
If you want to add this path permanently, you need to type pathtool
,
browse to the root folder of JSONLab and add to the list, then click "Save".
Then, run rehash
in MATLAB, and type "which savejson", if you see an
output, that means JSONLab is installed for MATLAB/Octave.
If you use MATLAB in a shared environment such as a Linux server, the
best way to add path is to type
mkdir ~/matlab/
nano ~/matlab/startup.m
and type addpath('/path/to/jsonlab')
in this file, save and exit the editor.
MATLAB will execute this file every time it starts. For Octave, the file
you need to edit is ~/.octaverc
, where "~"
represents your home directory.
To use the data compression features, please download the ZMat toolbox from
https://github.com/fangq/zmat/releases/latest and follow the instruction to
install ZMat first. The ZMat toolbox is required when compression is used on
MATLAB running in the -nojvm
mode or GNU Octave, or 'lzma/lzip/lz4/lz4hc'
compression methods are specified. ZMat can also compress large arrays that
MATLAB's Java-based compression API does not support.
Install JSONLab on Fedora 24 or later
JSONLab has been available as an official Fedora package since 2015. You may
install it directly using the below command
sudo dnf install octave-jsonlab
To enable data compression/decompression, you need to install octave-zmat
using
sudo dnf install octave-zmat
Install JSONLab on Arch Linux
JSONLab is also available on Arch Linux. You may install it using the below command
sudo pikaur -S jsonlab
Using jsave/jload
to share workspace
Starting from JSONLab v2.0, we provide a pair of functions, jsave/jload
to store
and retrieve variables from the current workspace, similar to the save/load
functions in MATLAB and Octave. The files that jsave/jload
reads/writes is by
default a binary JData file with a suffix .jamm
. The file size is comparable
(can be smaller if use lzma
compression) to .mat
files. This feature
is currently experimental.
The main benefits of using .jamm file to share matlab variables include
- a
.jamm
file can be 50% smaller than a.mat
file when using
jsave(..., "compression","lzma")
; the only drawback is longer saving time. - a
.jamm
file can be readily read/opened among many programming environments, including
Python, JavaScript, Go, Java etc, where.mat
file support is not generally available.
Parsers of.jamm
is largely compatible with UBJSON's parsers available at
http://ubjson.org/?page_id=48 - a
.jamm
file is quasi-human-readable, one can see the internal data fields
even in a command line, for example usingstrings -n 2 file.jamm | astyle
,
making the binary data easy to be understood, shared and reused. jsave/jload
can also use MessagePack and JSON formats as the underlying
data storage format, addressing needs from diverse applications.
MessagePack parsers are readily available at https://msgpack.org/
jsave.m
jsave % save the current workspace to jamdata.jamm
jsave mydata.jamm
jsave('mydata.jamm','vars',{'var1','var2'})
jsave('mydata.jamm','compression','lzma')
jsave('mydata.json','compression','gzip')
jload.m
jload % load variables from jamdata.jamm to the current workspace
jload mydata.jamm % load variables from mydata.jamm
vars=jload('mydata.jamm','vars',{'var1','var2'}) % return vars.var1, vars.var2
jload('mydata.jamm','simplifycell',0)
jload('mydata.json')
Sharing JSONLab created data files in Python
Despite the use of portable data annotation defined by the JData Specification,
the output JSON files created by JSONLab are 100% JSON compatible (with
the exception that long strings may be broken into multiple lines for better
readability). Therefore, JSONLab-created JSON files (.json, .jnii, .jnirs
etc)
can be readily read and written by nearly all existing JSON parsers, including
the built-in json
module parser in Python.
However, we strongly recommend one to use a lightweight jdata
module,
developed by the same author, to perform the extra JData encoding and decoding
and convert JSON data directly to convenient Python/Numpy data structures.
The jdata
module can also directly read/write UBJSON/Binary JData outputs
from JSONLab (.bjd, .ubj, .bnii, .bnirs, .jamm
etc). Using binary JData
files are exptected to produce much smaller file sizes and faster parsing,
while maintainining excellent portability and generality.
In short, to conveniently read/write data files created by JSONLab into Python,
whether they are JSON based or binary JData/UBJSON based, one just need to download
the below two light-weight python modules:
- jdata: PyPi: https://pypi.org/project/jdata/ ; Github: https://github.com/fangq/pyjdata
- bjdata PyPi: https://pypi.org/project/bjdata/ ; Github: https://github.com/fangq/pybj
To install these modules on Python 2.x, please first check if your system has
pip
and numpy
, if not, please install it by running (using Ubuntu/Debian as example)
sudo apt-get install python-pip python3-pip python-numpy python3-numpy
After the installation is done, one can then install the jdata
and bjdata
modules by
pip install jdata --user
pip install bjdata --user
To install these modules for Python 3.x, please replace pip
by pip3
.
If one prefers to install these modules globally for all users, simply
execute the above commands using sudo
and remove the --user
flag.
The above modules require built-in Python modules json
and NumPy (numpy
).
Once the necessary modules are installed, one can type python
(or python3
), and run
import jdata as jd
import numpy as np
from collections import OrderedDict
data1=jd.loadt('myfile.json',object_pairs_hook=OrderedDict);
data2=jd.loadb('myfile.ubj',object_pairs_hook=OrderedDict);
data3=jd.loadb('myfile.jamm',object_pairs_hook=OrderedDict);
where jd.loadt()
function loads a text-based JSON file, performs
JData decoding and converts the enclosed data into Python dict
, list
and numpy
objects. Similarly, jd.loadb()
function loads a binary
JData/UBJSON file and performs similar conversions. One can directly call
jd.load()
to open JSONLab (and derived toolboxes such as jnifti:
https://github.com/fangq/jnifti or jsnirfy: https://github.com/fangq/jsnirfy)
generated files based on their respective file suffix.
Similarly, the jd.savet()
, jd.saveb()
and jd.save
functions
can revert the direction and convert a Python/Numpy object into JData encoded
data structure and store as text-, binary- and suffix-determined output files,
respectively.