added openIndexed method, which allows indexing of tar file from predetermined meta data file
This commit is contained in:
parent
813e2431d7
commit
73bec97625
|
|
@ -0,0 +1,63 @@
|
|||
The author of "jsonlab" toolbox is Qianqian Fang. Qianqian
|
||||
is currently an Assistant Professor in the Department of Bioengineering,
|
||||
Northeastern University.
|
||||
|
||||
Address: Qianqian Fang
|
||||
Department of Bioengineering
|
||||
Northeastern University
|
||||
212A Lake Hall
|
||||
360 Huntington Ave, Boston, MA 02115, USA
|
||||
Office: 503 Holmes Hall
|
||||
Phone[O]: 617-373-3829
|
||||
URL: http://fanglab.org
|
||||
Email: <q.fang at neu.edu> and <fangqq at gmail.com>
|
||||
|
||||
|
||||
The script loadjson.m was built upon previous works by
|
||||
|
||||
- Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
|
||||
date: 2009/11/02
|
||||
- François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
|
||||
date: 2009/03/22
|
||||
- Joel Feenstra: http://www.mathworks.com/matlabcentral/fileexchange/20565
|
||||
date: 2008/07/03
|
||||
|
||||
The data compression/decompression utilities ({zlib,gzip,base64}{encode,decode}.m)
|
||||
were copied from
|
||||
|
||||
- "Byte encoding utilities" by Kota Yamaguchi
|
||||
https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
date: 2013/01/04
|
||||
|
||||
|
||||
This toolbox contains patches submitted by the following contributors:
|
||||
|
||||
- Blake Johnson <bjohnso at bbn.com>
|
||||
part of revision 341
|
||||
|
||||
- Niclas Borlin <Niclas.Borlin at cs.umu.se>
|
||||
various fixes in revision 394, including
|
||||
- loadjson crashes for all-zero sparse matrix.
|
||||
- loadjson crashes for empty sparse matrix.
|
||||
- Non-zero size of 0-by-N and N-by-0 empty matrices is lost after savejson/loadjson.
|
||||
- loadjson crashes for sparse real column vector.
|
||||
- loadjson crashes for sparse complex column vector.
|
||||
- Data is corrupted by savejson for sparse real row vector.
|
||||
- savejson crashes for sparse complex row vector.
|
||||
|
||||
- Yul Kang <yul.kang.on at gmail.com>
|
||||
patches for svn revision 415.
|
||||
- savejson saves an empty cell array as [] instead of null
|
||||
- loadjson differentiates an empty struct from an empty array
|
||||
|
||||
- Mykhailo Bratukha <bratukha.m at gmail.com>
|
||||
(Pull#14) Bug fix: File path is wrongly inerpreted as JSON string
|
||||
|
||||
- Insik Kim <insik92 at gmail.com>
|
||||
(Pull#12) Bug fix: Resolving bug that cell type is converted to json with transposed data
|
||||
|
||||
- Sertan Senturk <contact at sertansenturk.com>
|
||||
(Pull#10,#11) Feature: Added matlab object saving to savejson and saveubjson
|
||||
|
||||
- Paul Koprowski <https://github.com/pjkoprowski>
|
||||
(Issue#29) Feature: Added support to save MATLAB tables to json.
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
============================================================================
|
||||
|
||||
JSONlab - a toolbox to encode/decode JSON/UBJSON files in MATLAB/Octave
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
JSONlab ChangeLog (key features marked by *):
|
||||
|
||||
== JSONlab 1.9 (codename: Magnus - alpha), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2019-05-06 [25ad795] unescape string in loadjson.m
|
||||
2019-05-04 [2e317c9] explain extra compression fields
|
||||
2019-05-02 [1b1be65] avoid side effect of removing singletarray
|
||||
2019-05-02*[8360fd1] support zmat based base64 encoding and decoding
|
||||
2019-05-01*[c797bb2] integrating zmat, for zlib/gzip data compression
|
||||
2019-04-29 [70551fe] remove warnings from matlab
|
||||
2019-04-28 [0d61c4b] complete data compression support, close #52
|
||||
2019-04-27 [804115b] avoid typecast error
|
||||
2019-04-27 [c166aa7] change default compressarraysize to 100
|
||||
2019-04-27*[3322f6f] major new feature: support array compression and decompression
|
||||
2019-03-13*[9c01046] support saving function handles, close #51
|
||||
2019-03-13 [a8fde38] add option to parse string array or convert to char, close #50
|
||||
2019-03-12 [ed2645e] treat string array as cell array in newer matlab
|
||||
2018-11-18 [c3eb021] allow saving uint64 integers in saveubjson, fix #49
|
||||
|
||||
== JSONlab 1.8 (codename: Nominus), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2018-07-12 [03a6c25] update documentation, bump version to 1.8, tag Nominus
|
||||
2018-07-12*[1597106] add patch provided by pjkoprowski to support MATLAB table, add RowNames support, fix #29
|
||||
2018-07-12 [f16cc57] fix #31, throw an error when : array construct is used
|
||||
2018-07-12 [956e000] drop octave 3.x support, fix ubjson error in octave
|
||||
2018-07-12 [e090f0a] fix octave warning for saveubjson
|
||||
2018-07-12*[34284c7] fix issues #34 #39 #44 and #45, support double-quoted strings
|
||||
2017-09-06 [474d8c8] Merge pull request #41 from dasantonym/master
|
||||
2017-08-07*[38b24fb] added package.json to be able to intall via npm package manager, converted readme to utf-8, added basic .gitignore file
|
||||
2017-07-19 [ae7a5d9] Merge pull request #40 from astorfi/master
|
||||
2017-07-17 [154ef61] Rename README.txt to README.rst
|
||||
2017-03-27 [31b5bdc] simplify condition flow in matching_bracket
|
||||
2017-03-27 [86ef12a] avoid error in matlab 2017a, close #34
|
||||
2017-02-18 [4a09ac3] Merge pull request #32 from vrichter/master
|
||||
2017-02-14 [e67d3a3] respect integer types
|
||||
|
||||
== JSONlab 1.5 (codename: Nominus - alpha), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2017/01/02 *use Big-endian format to store floating points (d/D) in saveubjson (Issue #25)
|
||||
2017/01/02 *speedup parsing large unstructured data by 2x (Issue #9)
|
||||
2017/01/01 make parsing independent of white space (Issue #30)
|
||||
2016/08/27 allow to parse array of homogeneous elements (Issue 5)
|
||||
2016/08/22 permit [] inside file names in savejson
|
||||
2016/01/06 fix a bug that prevents saving to a file in savejson
|
||||
|
||||
|
||||
== JSONlab 1.2 (codename: Optimus - Update 2), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2015/12/16 *replacing string concatenation by str cells to gain 2x speed in savejson (Issue#17)
|
||||
2015/12/11 fix FileName option case bug (SVN rev#495)
|
||||
2015/12/11 add SingletCell option, add SingletArray to replace NoRowBracket (Issue#15,#8)
|
||||
2015/11/10 fix bug for inerpreting file names as JSON string - by Mykhailo Bratukha (Pull#14)
|
||||
2015/10/16 fix bug for cell with transposed data - by Insik Kim (Pull#12)
|
||||
2015/09/25 support exporting matlab object to JSON - by Sertan Senturk (Pull#10, #11)
|
||||
|
||||
== JSONlab 1.1 (codename: Optimus - Update 1), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2015/05/05 *massively accelerating loadjson for parsing large collection of unstructured small objects
|
||||
2015/05/05 force array bracket in 1x1 struct to maintain depth (Issue#1)
|
||||
2015/05/05 parse logicals in loadjson
|
||||
2015/05/05 make options case insensitive
|
||||
2015/05/01 reading unicode encoded json files (thanks to Sertan Senturk,Issue#3)
|
||||
2015/04/30 allow \uXXXX to represent a unicode in a string (Issue#2)
|
||||
2015/03/30 save a 0x0 solid real empty array as null and handel empty struct array
|
||||
2015/03/30 properly handle escape characters in a string
|
||||
2015/01/24 *implement the UBJSON Draft12 new name format
|
||||
2015/01/13 correct cell array indentation inconsistency
|
||||
|
||||
== JSONlab 1.0 (codename: Optimus - Final), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2015/01/02 polish help info for all major functions, update examples, finalize 1.0
|
||||
2014/12/19 fix a bug to strictly respect NoRowBracket in savejson
|
||||
|
||||
== JSONlab 1.0.0-RC2 (codename: Optimus - RC2), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2014/11/22 show progress bar in loadjson ('ShowProgress')
|
||||
2014/11/17 *add Compact option in savejson to output compact JSON format ('Compact')
|
||||
2014/11/17 add FastArrayParser in loadjson to specify fast parser applicable levels
|
||||
2014/09/18 *start official github mirror: https://github.com/fangq/jsonlab
|
||||
|
||||
== JSONlab 1.0.0-RC1 (codename: Optimus - RC1), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2014/09/17 fix several compatibility issues when running on octave versions 3.2-3.8
|
||||
2014/09/17 *support 2D cell and struct arrays in both savejson and saveubjson
|
||||
2014/08/04 escape special characters in a JSON string
|
||||
2014/02/16 fix a bug when saving ubjson files
|
||||
|
||||
== JSONlab 0.9.9 (codename: Optimus - beta), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2014/01/22 use binary read and write in saveubjson and loadubjson
|
||||
|
||||
== JSONlab 0.9.8-1 (codename: Optimus - alpha update 1), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2013/10/07 better round-trip conservation for empty arrays and structs (patch submitted by Yul Kang)
|
||||
|
||||
== JSONlab 0.9.8 (codename: Optimus - alpha), FangQ <q.fang <at> neu.edu> ==
|
||||
2013/08/23 *universal Binary JSON (UBJSON) support, including both saveubjson and loadubjson
|
||||
|
||||
== JSONlab 0.9.1 (codename: Rodimus, update 1), FangQ <q.fang <at> neu.edu> ==
|
||||
2012/12/18 *handling of various empty and sparse matrices (fixes submitted by Niclas Borlin)
|
||||
|
||||
== JSONlab 0.9.0 (codename: Rodimus), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2012/06/17 *new format for an invalid leading char, unpacking hex code in savejson
|
||||
2012/06/01 support JSONP in savejson
|
||||
2012/05/25 fix the empty cell bug (reported by Cyril Davin)
|
||||
2012/04/05 savejson can save to a file (suggested by Patrick Rapin)
|
||||
|
||||
== JSONlab 0.8.1 (codename: Sentiel, Update 1), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2012/02/28 loadjson quotation mark escape bug, see http://bit.ly/yyk1nS
|
||||
2012/01/25 patch to handle root-less objects, contributed by Blake Johnson
|
||||
|
||||
== JSONlab 0.8.0 (codename: Sentiel), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2012/01/13 *speed up loadjson by 20 fold when parsing large data arrays in matlab
|
||||
2012/01/11 remove row bracket if an array has 1 element, suggested by Mykel Kochenderfer
|
||||
2011/12/22 *accept sequence of 'param',value input in savejson and loadjson
|
||||
2011/11/18 fix struct array bug reported by Mykel Kochenderfer
|
||||
|
||||
== JSONlab 0.5.1 (codename: Nexus Update 1), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2011/10/21 fix a bug in loadjson, previous code does not use any of the acceleration
|
||||
2011/10/20 loadjson supports JSON collections - concatenated JSON objects
|
||||
|
||||
== JSONlab 0.5.0 (codename: Nexus), FangQ <q.fang <at> neu.edu> ==
|
||||
|
||||
2011/10/16 package and release jsonlab 0.5.0
|
||||
2011/10/15 *add json demo and regression test, support cpx numbers, fix double quote bug
|
||||
2011/10/11 *speed up readjson dramatically, interpret _Array* tags, show data in root level
|
||||
2011/10/10 create jsonlab project, start jsonlab website, add online documentation
|
||||
2011/10/07 *speed up savejson by 25x using sprintf instead of mat2str, add options support
|
||||
2011/10/06 *savejson works for structs, cells and arrays
|
||||
2011/09/09 derive loadjson from JSON parser from MATLAB Central, draft savejson.m
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
Copyright 2011-2019 Qianqian Fang <q.fang <at> neu.edu>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those of the
|
||||
authors and should not be interpreted as representing official policies, either expressed
|
||||
or implied, of the copyright holders.
|
||||
|
||||
|
||||
|
||||
|
||||
For the included compression/decompression utilities (base64encode.m, base64decode.m,
|
||||
gzipencode.m, gzipdecode.m, zlibencode.m, zlibdecode.m), the author Kota Yamaguchi
|
||||
requires the following copyright declaration:
|
||||
|
||||
Copyright (c) 2012, Kota Yamaguchi
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,579 @@
|
|||
##############################################################################
|
||||
JSONLab: An open-source MATLAB/Octave JSON encoder and decoder
|
||||
##############################################################################
|
||||
|
||||
* Copyright (C) 2011-2019 Qianqian Fang <q.fang at neu.edu>
|
||||
* License: BSD, License_BSD.txt for details
|
||||
* Version: 1.9 (Magnus - alpha)
|
||||
|
||||
|
||||
#################
|
||||
Table of Contents
|
||||
#################
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 3
|
||||
|
||||
============
|
||||
What's New
|
||||
============
|
||||
|
||||
JSONLab v1.9 is the alpha release of the next milestone - code named "Magnus".
|
||||
Notable changes are summarized below, key features marked by *:
|
||||
|
||||
- 2019-05-06 [25ad795] unescape string in loadjson.m
|
||||
- 2019-05-04 [2e317c9] explain extra compression fields
|
||||
- 2019-05-02 [1b1be65] avoid side effect of removing singletarray
|
||||
- 2019-05-02*[8360fd1] support zmat based base64 encoding and decoding
|
||||
- 2019-05-01*[c797bb2] integrating zmat, for zlib/gzip data compression
|
||||
- 2019-04-29 [70551fe] remove warnings from matlab
|
||||
- 2019-04-28 [0d61c4b] complete data compression support, close #52
|
||||
- 2019-04-27 [804115b] avoid typecast error
|
||||
- 2019-04-27 [c166aa7] change default compressarraysize to 100
|
||||
- 2019-04-27*[3322f6f] major new feature: support array compression and decompression
|
||||
- 2019-03-13*[9c01046] support saving function handles, close #51
|
||||
- 2019-03-13 [a8fde38] add option to parse string array or convert to char, close #50
|
||||
- 2019-03-12 [ed2645e] treat string array as cell array in newer matlab
|
||||
- 2018-11-18 [c3eb021] allow saving uint64 integers in saveubjson, fix #49
|
||||
|
||||
The biggest change in this release, compared to v1.8 released in July 2018,
|
||||
is the support of data compression via the 'Compression' option for both
|
||||
savejson and saveubjson. Two compression methods are currently supported -
|
||||
"zlib" and "gzip". The compression interfaces, zlibencode/zlibdecode/gzipencode/
|
||||
gzipdecode are modified from the "Byte Encoding Utilities" by Kota Yamaguchi [1],
|
||||
which has built-in support for java-based compression in MATLAB (when jvm is
|
||||
enabled). To support Octave, as well as MATLAB in "nojvm" mode, a mex-based
|
||||
data compression/encoding toolbox, ZMat [2], written by Qianqian Fang, takes priority
|
||||
over the java-based utilities, if installed. For savejson, a 'base64' encoding is
|
||||
applied to convert the compressed binary stream into a string; 'base64' encoding
|
||||
is not used in saveubjson. The encoding and restoration of the binary matlab arrays
|
||||
are automatically handled in save*json/load*json round-trip conversions.
|
||||
|
||||
To save matlab data with compression, one simply append 'Compression', 'method' pair
|
||||
in the savejson/saveubjson call. For example
|
||||
|
||||
.. code:: matlab
|
||||
|
||||
jsonstr=savejson('',mydata,'compression','zlib');
|
||||
data=loadjson(jsonstr);
|
||||
|
||||
In addition, the below features are added to JSONLab
|
||||
|
||||
* save function handles
|
||||
* support saving "string" class in MATLAB
|
||||
* fix two bugs in saveubjson
|
||||
* unescape strings in loadjson
|
||||
|
||||
|
||||
- [1] https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
- [2] http://github.com/fangq/zmat
|
||||
|
||||
============
|
||||
Introduction
|
||||
============
|
||||
|
||||
JSONLab is a free and open-source implementation of a JSON/UBJSON encoder
|
||||
and a decoder in the native MATLAB language. It can be used to convert a MATLAB
|
||||
data structure (array, struct, cell, struct array and cell array) into
|
||||
JSON/UBJSON formatted strings, or to decode a JSON/UBJSON file into MATLAB
|
||||
data structure. JSONLab supports both MATLAB and `GNU Octave <http://www.gnu.org/software/octave/>`_ (a free MATLAB clone).
|
||||
|
||||
JSON (`JavaScript Object Notation <http://www.json.org/>`_) is a highly portable,
|
||||
human-readable and " `fat-free <http://en.wikipedia.org/wiki/JSON>`_" text format
|
||||
to represent complex and hierarchical data. It is as powerful as `XML <http://en.wikipedia.org/wiki/XML>`_,
|
||||
but less verbose. JSON format is widely used for data-exchange in applications.
|
||||
|
||||
UBJSON (`Universal Binary JSON <http://ubjson.org/>`_) is a binary JSON format, specifically
|
||||
optimized for compact file size and better performance while keeping
|
||||
the semantics as simple as the text-based JSON format. Using the UBJSON
|
||||
format allows to wrap complex binary data in a flexible and extensible
|
||||
structure, making it possible to process complex and large dataset
|
||||
without accuracy loss due to text conversions.
|
||||
|
||||
We envision that both JSON and its binary version will play important roles
|
||||
as mainstream data-exchange formats for scientific research.
|
||||
It has both the flexibility and generality as offered by other popular
|
||||
general-purpose file specifications, such as `HDF5 <http://www.hdfgroup.org/HDF5/whatishdf5.html>`_,
|
||||
but with significantly reduced complexity and excellent readability.
|
||||
|
||||
================
|
||||
Installation
|
||||
================
|
||||
|
||||
The installation of JSONLab is no different than any other simple
|
||||
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:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
addpath('/path/to/jsonlab');
|
||||
|
||||
If you want to add this path permanently, you need to type "pathtool",
|
||||
browse to the zmat root folder 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
|
||||
|
||||
.. code:: shell
|
||||
|
||||
mkdir ~/matlab/
|
||||
nano ~/matlab/startup.m
|
||||
|
||||
and type addpath('/path/to/jsonlab') in this file, save and quit the editor.
|
||||
MATLAB will execute this file every time it starts. For Octave, the file
|
||||
you need to edit is ~/.octaverc , where "~" is your home directory.
|
||||
|
||||
|
||||
================
|
||||
Using JSONLab
|
||||
================
|
||||
|
||||
JSONLab provides two functions, loadjson.m -- a MATLAB->JSON decoder,
|
||||
and savejson.m -- a MATLAB->JSON encoder, for the text-based JSON, and
|
||||
two equivallent functions -- loadubjson and saveubjson for the binary
|
||||
JSON. The detailed help info for the four functions can be found below:
|
||||
|
||||
----------
|
||||
loadjson.m
|
||||
----------
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
data=loadjson(fname,opt)
|
||||
or
|
||||
data=loadjson(fname,'param1',value1,'param2',value2,...)
|
||||
|
||||
parse a JSON (JavaScript Object Notation) file or string
|
||||
|
||||
authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2011/09/09, including previous works from
|
||||
|
||||
Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
|
||||
created on 2009/11/02
|
||||
François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
|
||||
created on 2009/03/22
|
||||
Joel Feenstra:
|
||||
http://www.mathworks.com/matlabcentral/fileexchange/20565
|
||||
created on 2008/07/03
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
fname: input file name, if fname contains "{}" or "[]", fname
|
||||
will be interpreted as a JSON string
|
||||
opt: a struct to store parsing options, opt can be replaced by
|
||||
a list of ('param',value) pairs - the param string is equivallent
|
||||
to a field in opt. opt can have the following
|
||||
fields (first in [.|.] is the default)
|
||||
|
||||
opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat
|
||||
for each element of the JSON data, and group
|
||||
arrays based on the cell2mat rules.
|
||||
opt.FastArrayParser [1|0 or integer]: if set to 1, use a
|
||||
speed-optimized array parser when loading an
|
||||
array object. The fast array parser may
|
||||
collapse block arrays into a single large
|
||||
array similar to rules defined in cell2mat; 0 to
|
||||
use a legacy parser; if set to a larger-than-1
|
||||
value, this option will specify the minimum
|
||||
dimension to enable the fast array parser. For
|
||||
example, if the input is a 3D array, setting
|
||||
FastArrayParser to 1 will return a 3D array;
|
||||
setting to 2 will return a cell array of 2D
|
||||
arrays; setting to 3 will return to a 2D cell
|
||||
array of 1D vectors; setting to 4 will return a
|
||||
3D cell array.
|
||||
opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
opt.ParseStringArray [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
|
||||
output:
|
||||
dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
and [...] are converted to arrays
|
||||
|
||||
examples:
|
||||
dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}')
|
||||
dat=loadjson(['examples' filesep 'example1.json'])
|
||||
dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1)
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
|
||||
----------
|
||||
savejson.m
|
||||
----------
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
json=savejson(rootname,obj,filename)
|
||||
or
|
||||
json=savejson(rootname,obj,opt)
|
||||
json=savejson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
|
||||
convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
|
||||
Object Notation) string
|
||||
|
||||
author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2011/09/09
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
rootname: the name of the root-object, when set to '', the root name
|
||||
is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
the MATLAB variable name will be used as the root name.
|
||||
obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
class instance).
|
||||
filename: a string for the file name to save the output JSON data.
|
||||
opt: a struct for additional options, ignore to use default values.
|
||||
opt can have the following fields (first in [.|.] is the default)
|
||||
|
||||
opt.FileName [''|string]: a file name to save the output JSON data
|
||||
opt.FloatFormat ['%.10g'|string]: format to show each numeric element
|
||||
of a 1D/2D array;
|
||||
opt.ArrayIndent [1|0]: if 1, output explicit data array with
|
||||
precedent indentation; if 0, no indentation
|
||||
opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
|
||||
array in JSON array format; if sets to 1, an
|
||||
array will be shown as a struct with fields
|
||||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
sparse arrays, the non-zero elements will be
|
||||
saved to _ArrayData_ field in triplet-format i.e.
|
||||
(ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
with a value of 1; for a complex array, the
|
||||
_ArrayData_ array will include two columns
|
||||
(4 for sparse) to record the real and imaginary
|
||||
parts, and also "_ArrayIsComplex_":1 is added.
|
||||
opt.ParseLogical [0|1]: if this is set to 1, logical array elem
|
||||
will use true/false rather than 1/0.
|
||||
opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
numerical element will be shown without a square
|
||||
bracket, unless it is the root object; if 0, square
|
||||
brackets are forced for any numerical arrays.
|
||||
opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
even it has only one element; if 0, brackets
|
||||
are ignored when a cell has only 1 element.
|
||||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson
|
||||
will use the name of the passed obj variable as the
|
||||
root object name; if obj is an expression and
|
||||
does not have a name, 'root' will be used; if this
|
||||
is set to 0 and rootname is empty, the root level
|
||||
will be merged down to the lower level.
|
||||
opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern
|
||||
to represent +/-Inf. The matched pattern is '([-+]*)Inf'
|
||||
and $1 represents the sign. For those who want to use
|
||||
1e999 to represent Inf, they can set opt.Inf to '$11e999'
|
||||
opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern
|
||||
to represent NaN
|
||||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
for example, if opt.JSONP='foo', the JSON data is
|
||||
wrapped inside a function call as 'foo(...);'
|
||||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
back to the string form
|
||||
opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode.
|
||||
opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs)
|
||||
opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
method; currently only supports 'gzip' or 'zlib'. The
|
||||
data compression only applicable to numerical arrays
|
||||
in 3D or higher dimensions, or when ArrayToStruct
|
||||
is 1 for 1D or 2D arrays. If one wants to
|
||||
compress a long string, one must convert
|
||||
it to uint8 or int8 array first. The compressed
|
||||
array uses three extra fields
|
||||
"_ArrayCompressionMethod_": the opt.Compression value.
|
||||
"_ArrayCompressionSize_": a 1D interger array to
|
||||
store the pre-compressed (but post-processed)
|
||||
array dimensions, and
|
||||
"_ArrayCompressedData_": the "base64" encoded
|
||||
compressed binary array data.
|
||||
opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
element count is larger than this number.
|
||||
opt can be replaced by a list of ('param',value) pairs. The param
|
||||
string is equivallent to a field in opt and is case sensitive.
|
||||
output:
|
||||
json: a string in the JSON format (see http://json.org)
|
||||
|
||||
examples:
|
||||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
'SpecialData',[nan, inf, -inf]);
|
||||
savejson('jmesh',jsonmesh)
|
||||
savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g')
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
|
||||
-------------
|
||||
loadubjson.m
|
||||
-------------
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
data=loadubjson(fname,opt)
|
||||
or
|
||||
data=loadubjson(fname,'param1',value1,'param2',value2,...)
|
||||
|
||||
parse a JSON (JavaScript Object Notation) file or string
|
||||
|
||||
authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2013/08/01
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
fname: input file name, if fname contains "{}" or "[]", fname
|
||||
will be interpreted as a UBJSON string
|
||||
opt: a struct to store parsing options, opt can be replaced by
|
||||
a list of ('param',value) pairs - the param string is equivallent
|
||||
to a field in opt. opt can have the following
|
||||
fields (first in [.|.] is the default)
|
||||
|
||||
opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat
|
||||
for each element of the JSON data, and group
|
||||
arrays based on the cell2mat rules.
|
||||
opt.IntEndian [B|L]: specify the endianness of the integer fields
|
||||
in the UBJSON input data. B - Big-Endian format for
|
||||
integers (as required in the UBJSON specification);
|
||||
L - input integer fields are in Little-Endian order.
|
||||
opt.NameIsString [0|1]: for UBJSON Specification Draft 8 or
|
||||
earlier versions (JSONLab 1.0 final or earlier),
|
||||
the "name" tag is treated as a string. To load
|
||||
these UBJSON data, you need to manually set this
|
||||
flag to 1.
|
||||
|
||||
output:
|
||||
dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
and [...] are converted to arrays
|
||||
|
||||
examples:
|
||||
obj=struct('string','value','array',[1 2 3]);
|
||||
ubjdata=saveubjson('obj',obj);
|
||||
dat=loadubjson(ubjdata)
|
||||
dat=loadubjson(['examples' filesep 'example1.ubj'])
|
||||
dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1)
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
|
||||
-------------
|
||||
saveubjson.m
|
||||
-------------
|
||||
|
||||
|
||||
.. code-block:: matlab
|
||||
|
||||
json=saveubjson(rootname,obj,filename)
|
||||
or
|
||||
json=saveubjson(rootname,obj,opt)
|
||||
json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
|
||||
convert a MATLAB object (cell, struct or array) into a Universal
|
||||
Binary JSON (UBJSON) binary string
|
||||
|
||||
author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2013/08/17
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
rootname: the name of the root-object, when set to '', the root name
|
||||
is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
the MATLAB variable name will be used as the root name.
|
||||
obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
class instance)
|
||||
filename: a string for the file name to save the output UBJSON data
|
||||
opt: a struct for additional options, ignore to use default values.
|
||||
opt can have the following fields (first in [.|.] is the default)
|
||||
|
||||
opt.FileName [''|string]: a file name to save the output JSON data
|
||||
opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D
|
||||
array in JSON array format; if sets to 1, an
|
||||
array will be shown as a struct with fields
|
||||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
sparse arrays, the non-zero elements will be
|
||||
saved to _ArrayData_ field in triplet-format i.e.
|
||||
(ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
with a value of 1; for a complex array, the
|
||||
_ArrayData_ array will include two columns
|
||||
(4 for sparse) to record the real and imaginary
|
||||
parts, and also "_ArrayIsComplex_":1 is added.
|
||||
opt.ParseLogical [1|0]: if this is set to 1, logical array elem
|
||||
will use true/false rather than 1/0.
|
||||
opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
numerical element will be shown without a square
|
||||
bracket, unless it is the root object; if 0, square
|
||||
brackets are forced for any numerical arrays.
|
||||
opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
even it has only one element; if 0, brackets
|
||||
are ignored when a cell has only 1 element.
|
||||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson
|
||||
will use the name of the passed obj variable as the
|
||||
root object name; if obj is an expression and
|
||||
does not have a name, 'root' will be used; if this
|
||||
is set to 0 and rootname is empty, the root level
|
||||
will be merged down to the lower level.
|
||||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
for example, if opt.JSON='foo', the JSON data is
|
||||
wrapped inside a function call as 'foo(...);'
|
||||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
back to the string form
|
||||
opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
method; currently only supports 'gzip' or 'zlib'. The
|
||||
data compression only applicable to numerical arrays
|
||||
in 3D or higher dimensions, or when ArrayToStruct
|
||||
is 1 for 1D or 2D arrays. If one wants to
|
||||
compress a long string, one must convert
|
||||
it to uint8 or int8 array first. The compressed
|
||||
array uses three extra fields
|
||||
"_ArrayCompressionMethod_": the opt.Compression value.
|
||||
"_ArrayCompressionSize_": a 1D interger array to
|
||||
store the pre-compressed (but post-processed)
|
||||
array dimensions, and
|
||||
"_ArrayCompressedData_": the binary stream of
|
||||
the compressed binary array data WITHOUT
|
||||
'base64' encoding
|
||||
opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
element count is larger than this number.
|
||||
|
||||
opt can be replaced by a list of ('param',value) pairs. The param
|
||||
string is equivallent to a field in opt and is case sensitive.
|
||||
output:
|
||||
json: a binary string in the UBJSON format (see http://ubjson.org)
|
||||
|
||||
examples:
|
||||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
'SpecialData',[nan, inf, -inf]);
|
||||
saveubjson('jsonmesh',jsonmesh)
|
||||
saveubjson('jsonmesh',jsonmesh,'meshdata.ubj')
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
|
||||
---------
|
||||
examples
|
||||
---------
|
||||
|
||||
Under the ``"examples"`` folder, you can find several scripts to demonstrate the
|
||||
basic utilities of JSONLab. Running the ``"demo_jsonlab_basic.m"`` script, you
|
||||
will see the conversions from MATLAB data structure to JSON text and backward.
|
||||
In ``"jsonlab_selftest.m"``, we load complex JSON files downloaded from the Internet
|
||||
and validate the ``loadjson/savejson`` functions for regression testing purposes.
|
||||
Similarly, a ``"demo_ubjson_basic.m"`` script is provided to test the saveubjson
|
||||
and loadubjson functions for various matlab data structures.
|
||||
|
||||
Please run these examples and understand how JSONLab works before you use
|
||||
it to process your data.
|
||||
|
||||
=======================
|
||||
Known Issues and TODOs
|
||||
=======================
|
||||
|
||||
JSONLab has several known limitations. We are striving to make it more general
|
||||
and robust. Hopefully in a few future releases, the limitations become less.
|
||||
|
||||
Here are the known issues:
|
||||
|
||||
* 3D or higher dimensional cell/struct-arrays will be converted to 2D arrays
|
||||
|
||||
* When processing names containing multi-byte characters, Octave and MATLAB can give different field-names; you can use feature('DefaultCharacterSet','latin1') in MATLAB to get consistant results
|
||||
|
||||
* savejson can not handle class and dataset.
|
||||
|
||||
* saveubjson converts a logical array into a uint8 ([U]) array
|
||||
|
||||
* an unofficial N-D array count syntax is implemented in saveubjson. We are actively communicating with the UBJSON spec maintainer to investigate the possibility of making it upstream
|
||||
|
||||
* loadubjson can not parse all UBJSON Specification (Draft 9) compliant files, however, it can parse all UBJSON files produced by saveubjson.
|
||||
|
||||
==========================
|
||||
Contribution and feedback
|
||||
==========================
|
||||
|
||||
JSONLab is an open-source project. This means you can not only use it and modify
|
||||
it as you wish, but also you can contribute your changes back to JSONLab so
|
||||
that everyone else can enjoy the improvement. For anyone who want to contribute,
|
||||
please download JSONLab source code from its source code repositories by using the
|
||||
following command:
|
||||
|
||||
|
||||
.. code:: shell
|
||||
|
||||
git clone https://github.com/fangq/jsonlab.git jsonlab
|
||||
|
||||
or browsing the github site at
|
||||
|
||||
https://github.com/fangq/jsonlab
|
||||
|
||||
Please report any bugs or issues to the below URL:
|
||||
|
||||
https://github.com/fangq/jsonlab/issues
|
||||
|
||||
Sometimes, you may find it is necessary to modify JSONLab to achieve your
|
||||
goals, or attempt to modify JSONLab functions to fix a bug that you have
|
||||
encountered. If you are happy with your changes and willing to share those
|
||||
changes to the upstream author, you are recommended to create a pull-request
|
||||
on github.
|
||||
|
||||
To create a pull-request, you first need to "fork" jsonlab on Github by
|
||||
clicking on the "fork" button on top-right of jsonlab's github page. Once you forked
|
||||
jsonlab to your own directory, you should then implement the changes in your
|
||||
own fork. After thoroughly testing it and you are confident the modification
|
||||
is complete and effective, you can then click on the "New pull request"
|
||||
button, and on the left, select fangq/jsonlab as the "base". Then type
|
||||
in the description of the changes. You are responsible to format the code
|
||||
updates using the same convention (tab-width: 8, indentation: 4 spaces) as
|
||||
the upstream code.
|
||||
|
||||
We appreciate any suggestions and feedbacks from you. Please use the following
|
||||
mailing list to report any questions you may have regarding JSONLab:
|
||||
|
||||
https://github.com/fangq/jsonlab/issues
|
||||
|
||||
(Subscription to the mailing list is needed in order to post messages).
|
||||
|
||||
|
||||
==========================
|
||||
Acknowledgement
|
||||
==========================
|
||||
|
||||
---------
|
||||
zlibdecode.m, zlibencode.m, gzipencode.m, gzipdecode.m, base64encode.m, base64decode.m
|
||||
---------
|
||||
|
||||
* Author: Kota Yamaguchi
|
||||
* URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
* License: BSD License, see below
|
||||
|
||||
```
|
||||
Copyright (c) 2012, Kota Yamaguchi
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
|
@ -0,0 +1,565 @@
|
|||
===============================================================================
|
||||
= JSONLab =
|
||||
= An open-source MATLAB/Octave JSON encoder and decoder =
|
||||
===============================================================================
|
||||
|
||||
*Copyright (C) 2011-2019 Qianqian Fang <q.fang at neu.edu>
|
||||
*License: BSD, License_BSD.txt for details
|
||||
*Version: 1.9 (Magnus - alpha)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Table of Content:
|
||||
|
||||
0. What's New
|
||||
I. Introduction
|
||||
II. Installation
|
||||
III.Using JSONLab
|
||||
IV. Known Issues and TODOs
|
||||
V. Contribution and feedback
|
||||
V. Acknowledgement
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
0. What's New
|
||||
|
||||
JSONLab v1.9 is the alpha release of the next milestone - code named "Magnus".
|
||||
Notable changes are summarized below, key features marked by *:
|
||||
|
||||
2019-05-06 [25ad795] unescape string in loadjson.m
|
||||
2019-05-04 [2e317c9] explain extra compression fields
|
||||
2019-05-02 [1b1be65] avoid side effect of removing singletarray
|
||||
2019-05-02*[8360fd1] support zmat based base64 encoding and decoding
|
||||
2019-05-01*[c797bb2] integrating zmat, for zlib/gzip data compression
|
||||
2019-04-29 [70551fe] remove warnings from matlab
|
||||
2019-04-28 [0d61c4b] complete data compression support, close #52
|
||||
2019-04-27 [804115b] avoid typecast error
|
||||
2019-04-27 [c166aa7] change default compressarraysize to 100
|
||||
2019-04-27*[3322f6f] major new feature: support array compression and decompression
|
||||
2019-03-13*[9c01046] support saving function handles, close #51
|
||||
2019-03-13 [a8fde38] add option to parse string array or convert to char, close #50
|
||||
2019-03-12 [ed2645e] treat string array as cell array in newer matlab
|
||||
2018-11-18 [c3eb021] allow saving uint64 integers in saveubjson, fix #49
|
||||
|
||||
The biggest change in this release, compared to v1.8 released in July 2018,
|
||||
is the support of data compression via the 'Compression' option for both
|
||||
savejson and saveubjson. Two compression methods are currently supported -
|
||||
"zlib" and "gzip". The compression interfaces, zlibencode/zlibdecode/gzipencode/
|
||||
gzipdecode are modified from the "Byte Encoding Utilities" by Kota Yamaguchi [1],
|
||||
which has built-in support for java-based compression in MATLAB (when jvm is
|
||||
enabled). To support Octave, as well as MATLAB in "nojvm" mode, a mex-based
|
||||
data compression/encoding toolbox, ZMat [2], written by Qianqian Fang, takes priority
|
||||
over the java-based utilities, if installed. For savejson, a 'base64' encoding is
|
||||
applied to convert the compressed binary stream into a string; 'base64' encoding
|
||||
is not used in saveubjson. The encoding and restoration of the binary matlab arrays
|
||||
are automatically handled in save*json/load*json round-trip conversions.
|
||||
|
||||
To save matlab data with compression, one simply append 'Compression', 'method' pair
|
||||
in the savejson/saveubjson call. For example
|
||||
|
||||
jsonstr=savejson('',mydata,'compression','zlib');
|
||||
data=loadjson(jsonstr);
|
||||
|
||||
In addition, the below features are added to JSONLab
|
||||
|
||||
* save function handles
|
||||
* support saving "string" class in MATLAB
|
||||
* fix two bugs in saveubjson
|
||||
* unescape strings in loadjson
|
||||
|
||||
|
||||
* [1] https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
* [2] http://github.com/fangq/zmat
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
I. Introduction
|
||||
|
||||
JSONLab is a free and open-source implementation of a JSON/UBJSON encoder
|
||||
and a decoder in the native MATLAB language. It can be used to convert a MATLAB
|
||||
data structure (array, struct, cell, struct array and cell array) into
|
||||
JSON/UBJSON formatted strings, or to decode a JSON/UBJSON file into MATLAB
|
||||
data structure. JSONLab supports both MATLAB and
|
||||
[http://www.gnu.org/software/octave/ GNU Octave] (a free MATLAB clone).
|
||||
|
||||
JSON ([http://www.json.org/ JavaScript Object Notation]) is a highly portable,
|
||||
human-readable and "[http://en.wikipedia.org/wiki/JSON fat-free]" text format
|
||||
to represent complex and hierarchical data. It is as powerful as
|
||||
[http://en.wikipedia.org/wiki/XML XML], but less verbose. JSON format is widely
|
||||
used for data-exchange in applications, and is essential for the wild success
|
||||
of [http://en.wikipedia.org/wiki/Ajax_(programming) Ajax] and
|
||||
[http://en.wikipedia.org/wiki/Web_2.0 Web2.0].
|
||||
|
||||
UBJSON ([<http://ubjson.org/ Universal Binary JSON]) is a binary JSON format, specifically
|
||||
optimized for compact file size and better performance while keeping
|
||||
the semantics as simple as the text-based JSON format. Using the UBJSON
|
||||
format allows to wrap complex binary data in a flexible and extensible
|
||||
structure, making it possible to process complex and large dataset
|
||||
without accuracy loss due to text conversions.
|
||||
|
||||
We envision that both JSON and its binary version will serve as part of
|
||||
the mainstream data-exchange formats for scientific research in the future.
|
||||
It will provide the flexibility and generality achieved by other popular
|
||||
general-purpose file specifications, such as
|
||||
[http://www.hdfgroup.org/HDF5/whatishdf5.html HDF5], with significantly
|
||||
reduced complexity and enhanced performance.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
II. Installation
|
||||
|
||||
The installation of JSONLab is no different than any other simple
|
||||
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 zmat root folder 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 quit the editor.
|
||||
MATLAB will execute this file every time it starts. For Octave, the file
|
||||
you need to edit is ~/.octaverc , where "~" is your home directory.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
III.Using JSONLab
|
||||
|
||||
JSONLab provides two functions, loadjson.m -- a MATLAB->JSON decoder,
|
||||
and savejson.m -- a MATLAB->JSON encoder, for the text-based JSON, and
|
||||
two equivallent functions -- loadubjson and saveubjson for the binary
|
||||
JSON. The detailed help info for the four functions can be found below:
|
||||
|
||||
=== loadjson.m ===
|
||||
<pre>
|
||||
data=loadjson(fname,opt)
|
||||
or
|
||||
data=loadjson(fname,'param1',value1,'param2',value2,...)
|
||||
|
||||
parse a JSON (JavaScript Object Notation) file or string
|
||||
|
||||
authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2011/09/09, including previous works from
|
||||
|
||||
Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
|
||||
created on 2009/11/02
|
||||
François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
|
||||
created on 2009/03/22
|
||||
Joel Feenstra:
|
||||
http://www.mathworks.com/matlabcentral/fileexchange/20565
|
||||
created on 2008/07/03
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
fname: input file name, if fname contains "{}" or "[]", fname
|
||||
will be interpreted as a JSON string
|
||||
opt: a struct to store parsing options, opt can be replaced by
|
||||
a list of ('param',value) pairs - the param string is equivallent
|
||||
to a field in opt. opt can have the following
|
||||
fields (first in [.|.] is the default)
|
||||
|
||||
opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat
|
||||
for each element of the JSON data, and group
|
||||
arrays based on the cell2mat rules.
|
||||
opt.FastArrayParser [1|0 or integer]: if set to 1, use a
|
||||
speed-optimized array parser when loading an
|
||||
array object. The fast array parser may
|
||||
collapse block arrays into a single large
|
||||
array similar to rules defined in cell2mat; 0 to
|
||||
use a legacy parser; if set to a larger-than-1
|
||||
value, this option will specify the minimum
|
||||
dimension to enable the fast array parser. For
|
||||
example, if the input is a 3D array, setting
|
||||
FastArrayParser to 1 will return a 3D array;
|
||||
setting to 2 will return a cell array of 2D
|
||||
arrays; setting to 3 will return to a 2D cell
|
||||
array of 1D vectors; setting to 4 will return a
|
||||
3D cell array.
|
||||
opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
opt.ParseStringArray [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
|
||||
output:
|
||||
dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
and [...] are converted to arrays
|
||||
|
||||
examples:
|
||||
dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}')
|
||||
dat=loadjson(['examples' filesep 'example1.json'])
|
||||
dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1)
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
</pre>
|
||||
|
||||
=== savejson.m ===
|
||||
|
||||
<pre>
|
||||
json=savejson(rootname,obj,filename)
|
||||
or
|
||||
json=savejson(rootname,obj,opt)
|
||||
json=savejson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
|
||||
convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
|
||||
Object Notation) string
|
||||
|
||||
author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2011/09/09
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
rootname: the name of the root-object, when set to '', the root name
|
||||
is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
the MATLAB variable name will be used as the root name.
|
||||
obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
class instance).
|
||||
filename: a string for the file name to save the output JSON data.
|
||||
opt: a struct for additional options, ignore to use default values.
|
||||
opt can have the following fields (first in [.|.] is the default)
|
||||
|
||||
opt.FileName [''|string]: a file name to save the output JSON data
|
||||
opt.FloatFormat ['%.10g'|string]: format to show each numeric element
|
||||
of a 1D/2D array;
|
||||
opt.ArrayIndent [1|0]: if 1, output explicit data array with
|
||||
precedent indentation; if 0, no indentation
|
||||
opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
|
||||
array in JSON array format; if sets to 1, an
|
||||
array will be shown as a struct with fields
|
||||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
sparse arrays, the non-zero elements will be
|
||||
saved to _ArrayData_ field in triplet-format i.e.
|
||||
(ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
with a value of 1; for a complex array, the
|
||||
_ArrayData_ array will include two columns
|
||||
(4 for sparse) to record the real and imaginary
|
||||
parts, and also "_ArrayIsComplex_":1 is added.
|
||||
opt.ParseLogical [0|1]: if this is set to 1, logical array elem
|
||||
will use true/false rather than 1/0.
|
||||
opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
numerical element will be shown without a square
|
||||
bracket, unless it is the root object; if 0, square
|
||||
brackets are forced for any numerical arrays.
|
||||
opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
even it has only one element; if 0, brackets
|
||||
are ignored when a cell has only 1 element.
|
||||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson
|
||||
will use the name of the passed obj variable as the
|
||||
root object name; if obj is an expression and
|
||||
does not have a name, 'root' will be used; if this
|
||||
is set to 0 and rootname is empty, the root level
|
||||
will be merged down to the lower level.
|
||||
opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern
|
||||
to represent +/-Inf. The matched pattern is '([-+]*)Inf'
|
||||
and $1 represents the sign. For those who want to use
|
||||
1e999 to represent Inf, they can set opt.Inf to '$11e999'
|
||||
opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern
|
||||
to represent NaN
|
||||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
for example, if opt.JSONP='foo', the JSON data is
|
||||
wrapped inside a function call as 'foo(...);'
|
||||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
back to the string form
|
||||
opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode.
|
||||
opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs)
|
||||
opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
method; currently only supports 'gzip' or 'zlib'. The
|
||||
data compression only applicable to numerical arrays
|
||||
in 3D or higher dimensions, or when ArrayToStruct
|
||||
is 1 for 1D or 2D arrays. If one wants to
|
||||
compress a long string, one must convert
|
||||
it to uint8 or int8 array first. The compressed
|
||||
array uses three extra fields
|
||||
"_ArrayCompressionMethod_": the opt.Compression value.
|
||||
"_ArrayCompressionSize_": a 1D interger array to
|
||||
store the pre-compressed (but post-processed)
|
||||
array dimensions, and
|
||||
"_ArrayCompressedData_": the "base64" encoded
|
||||
compressed binary array data.
|
||||
opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
element count is larger than this number.
|
||||
opt can be replaced by a list of ('param',value) pairs. The param
|
||||
string is equivallent to a field in opt and is case sensitive.
|
||||
output:
|
||||
json: a string in the JSON format (see http://json.org)
|
||||
|
||||
examples:
|
||||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
'SpecialData',[nan, inf, -inf]);
|
||||
savejson('jmesh',jsonmesh)
|
||||
savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g')
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
</pre>
|
||||
|
||||
=== loadubjson.m ===
|
||||
|
||||
<pre>
|
||||
data=loadubjson(fname,opt)
|
||||
or
|
||||
data=loadubjson(fname,'param1',value1,'param2',value2,...)
|
||||
|
||||
parse a JSON (JavaScript Object Notation) file or string
|
||||
|
||||
authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2013/08/01
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
fname: input file name, if fname contains "{}" or "[]", fname
|
||||
will be interpreted as a UBJSON string
|
||||
opt: a struct to store parsing options, opt can be replaced by
|
||||
a list of ('param',value) pairs - the param string is equivallent
|
||||
to a field in opt. opt can have the following
|
||||
fields (first in [.|.] is the default)
|
||||
|
||||
opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat
|
||||
for each element of the JSON data, and group
|
||||
arrays based on the cell2mat rules.
|
||||
opt.IntEndian [B|L]: specify the endianness of the integer fields
|
||||
in the UBJSON input data. B - Big-Endian format for
|
||||
integers (as required in the UBJSON specification);
|
||||
L - input integer fields are in Little-Endian order.
|
||||
opt.NameIsString [0|1]: for UBJSON Specification Draft 8 or
|
||||
earlier versions (JSONLab 1.0 final or earlier),
|
||||
the "name" tag is treated as a string. To load
|
||||
these UBJSON data, you need to manually set this
|
||||
flag to 1.
|
||||
|
||||
output:
|
||||
dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
and [...] are converted to arrays
|
||||
|
||||
examples:
|
||||
obj=struct('string','value','array',[1 2 3]);
|
||||
ubjdata=saveubjson('obj',obj);
|
||||
dat=loadubjson(ubjdata)
|
||||
dat=loadubjson(['examples' filesep 'example1.ubj'])
|
||||
dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1)
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
</pre>
|
||||
|
||||
=== saveubjson.m ===
|
||||
|
||||
<pre>
|
||||
json=saveubjson(rootname,obj,filename)
|
||||
or
|
||||
json=saveubjson(rootname,obj,opt)
|
||||
json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
|
||||
convert a MATLAB object (cell, struct or array) into a Universal
|
||||
Binary JSON (UBJSON) binary string
|
||||
|
||||
author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
created on 2013/08/17
|
||||
|
||||
$Id$
|
||||
|
||||
input:
|
||||
rootname: the name of the root-object, when set to '', the root name
|
||||
is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
the MATLAB variable name will be used as the root name.
|
||||
obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
class instance)
|
||||
filename: a string for the file name to save the output UBJSON data
|
||||
opt: a struct for additional options, ignore to use default values.
|
||||
opt can have the following fields (first in [.|.] is the default)
|
||||
|
||||
opt.FileName [''|string]: a file name to save the output JSON data
|
||||
opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D
|
||||
array in JSON array format; if sets to 1, an
|
||||
array will be shown as a struct with fields
|
||||
"_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
sparse arrays, the non-zero elements will be
|
||||
saved to _ArrayData_ field in triplet-format i.e.
|
||||
(ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
with a value of 1; for a complex array, the
|
||||
_ArrayData_ array will include two columns
|
||||
(4 for sparse) to record the real and imaginary
|
||||
parts, and also "_ArrayIsComplex_":1 is added.
|
||||
opt.ParseLogical [1|0]: if this is set to 1, logical array elem
|
||||
will use true/false rather than 1/0.
|
||||
opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
numerical element will be shown without a square
|
||||
bracket, unless it is the root object; if 0, square
|
||||
brackets are forced for any numerical arrays.
|
||||
opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
even it has only one element; if 0, brackets
|
||||
are ignored when a cell has only 1 element.
|
||||
opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson
|
||||
will use the name of the passed obj variable as the
|
||||
root object name; if obj is an expression and
|
||||
does not have a name, 'root' will be used; if this
|
||||
is set to 0 and rootname is empty, the root level
|
||||
will be merged down to the lower level.
|
||||
opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
for example, if opt.JSON='foo', the JSON data is
|
||||
wrapped inside a function call as 'foo(...);'
|
||||
opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
back to the string form
|
||||
opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
method; currently only supports 'gzip' or 'zlib'. The
|
||||
data compression only applicable to numerical arrays
|
||||
in 3D or higher dimensions, or when ArrayToStruct
|
||||
is 1 for 1D or 2D arrays. If one wants to
|
||||
compress a long string, one must convert
|
||||
it to uint8 or int8 array first. The compressed
|
||||
array uses three extra fields
|
||||
"_ArrayCompressionMethod_": the opt.Compression value.
|
||||
"_ArrayCompressionSize_": a 1D interger array to
|
||||
store the pre-compressed (but post-processed)
|
||||
array dimensions, and
|
||||
"_ArrayCompressedData_": the binary stream of
|
||||
the compressed binary array data WITHOUT
|
||||
'base64' encoding
|
||||
opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
element count is larger than this number.
|
||||
|
||||
opt can be replaced by a list of ('param',value) pairs. The param
|
||||
string is equivallent to a field in opt and is case sensitive.
|
||||
output:
|
||||
json: a binary string in the UBJSON format (see http://ubjson.org)
|
||||
|
||||
examples:
|
||||
jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
'SpecialData',[nan, inf, -inf]);
|
||||
saveubjson('jsonmesh',jsonmesh)
|
||||
saveubjson('jsonmesh',jsonmesh,'meshdata.ubj')
|
||||
|
||||
license:
|
||||
BSD, see LICENSE_BSD.txt file for details
|
||||
</pre>
|
||||
|
||||
|
||||
=== examples ===
|
||||
|
||||
Under the "examples" folder, you can find several scripts to demonstrate the
|
||||
basic utilities of JSONLab. Running the "demo_jsonlab_basic.m" script, you
|
||||
will see the conversions from MATLAB data structure to JSON text and backward.
|
||||
In "jsonlab_selftest.m", we load complex JSON files downloaded from the Internet
|
||||
and validate the loadjson/savejson functions for regression testing purposes.
|
||||
Similarly, a "demo_ubjson_basic.m" script is provided to test the saveubjson
|
||||
and loadubjson functions for various matlab data structures.
|
||||
|
||||
Please run these examples and understand how JSONLab works before you use
|
||||
it to process your data.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
IV. Known Issues and TODOs
|
||||
|
||||
JSONLab has several known limitations. We are striving to make it more general
|
||||
and robust. Hopefully in a few future releases, the limitations become less.
|
||||
|
||||
Here are the known issues:
|
||||
|
||||
# 3D or higher dimensional cell/struct-arrays will be converted to 2D arrays;
|
||||
# When processing names containing multi-byte characters, Octave and MATLAB \
|
||||
can give different field-names; you can use feature('DefaultCharacterSet','latin1') \
|
||||
in MATLAB to get consistant results
|
||||
# savejson can not handle class and dataset.
|
||||
# saveubjson converts a logical array into a uint8 ([U]) array
|
||||
# an unofficial N-D array count syntax is implemented in saveubjson. We are \
|
||||
actively communicating with the UBJSON spec maintainer to investigate the \
|
||||
possibility of making it upstream
|
||||
# loadubjson can not parse all UBJSON Specification (Draft 9) compliant \
|
||||
files, however, it can parse all UBJSON files produced by saveubjson.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
V. Contribution and feedback
|
||||
|
||||
JSONLab is an open-source project. This means you can not only use it and modify
|
||||
it as you wish, but also you can contribute your changes back to JSONLab so
|
||||
that everyone else can enjoy the improvement. For anyone who want to contribute,
|
||||
please download JSONLab source code from its source code repositories by using the
|
||||
following command:
|
||||
|
||||
git clone https://github.com/fangq/jsonlab.git jsonlab
|
||||
|
||||
or browsing the github site at
|
||||
|
||||
https://github.com/fangq/jsonlab
|
||||
|
||||
Please report any bugs or issues to the below URL:
|
||||
|
||||
https://github.com/fangq/jsonlab/issues
|
||||
|
||||
Sometimes, you may find it is necessary to modify JSONLab to achieve your
|
||||
goals, or attempt to modify JSONLab functions to fix a bug that you have
|
||||
encountered. If you are happy with your changes and willing to share those
|
||||
changes to the upstream author, you are recommended to create a pull-request
|
||||
on github.
|
||||
|
||||
To create a pull-request, you first need to "fork" jsonlab on Github by
|
||||
clicking on the "fork" button on top-right of jsonlab's github page. Once you forked
|
||||
jsonlab to your own directory, you should then implement the changes in your
|
||||
own fork. After thoroughly testing it and you are confident the modification
|
||||
is complete and effective, you can then click on the "New pull request"
|
||||
button, and on the left, select fangq/jsonlab as the "base". Then type
|
||||
in the description of the changes. You are responsible to format the code
|
||||
updates using the same convention (tab-width: 8, indentation: 4 spaces) as
|
||||
the upstream code.
|
||||
|
||||
We appreciate any suggestions and feedbacks from you. Please use the following
|
||||
mailing list to report any questions you may have regarding JSONLab:
|
||||
|
||||
https://github.com/fangq/jsonlab/issues
|
||||
|
||||
(Subscription to the mailing list is needed in order to post messages).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
V. Acknowledgement
|
||||
|
||||
This toolbox contains modified functions from the below toolboxes:
|
||||
|
||||
== zlibdecode.m, zlibencode.m, gzipencode.m, gzipdecode.m, base64encode.m, base64decode.m ==
|
||||
|
||||
* Author: Kota Yamaguchi
|
||||
* URL:https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
* License: BSD License, see below
|
||||
|
||||
Copyright (c) 2012, Kota Yamaguchi
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
function output = base64decode(input)
|
||||
import jsonlab.*
|
||||
%BASE64DECODE Decode Base64 string to a byte array.
|
||||
%
|
||||
% output = base64decode(input)
|
||||
%
|
||||
% The function takes a Base64 string INPUT and returns a uint8 array
|
||||
% OUTPUT. JAVA must be running to use this function. The result is always
|
||||
% given as a 1-by-N array, and doesn't retrieve the original dimensions.
|
||||
%
|
||||
% See also base64encode
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(uint8(input),0,'base64');
|
||||
return;
|
||||
end
|
||||
if(exist('OCTAVE_VERSION','builtin'))
|
||||
len=rem(numel(input),8)
|
||||
if(len)
|
||||
input=[input(:)', repmat(sprintf('\0'),1,(8-len))];
|
||||
end
|
||||
output = base64_decode(input);
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input), input = uint8(input); end
|
||||
|
||||
output = typecast(org.apache.commons.codec.binary.Base64.decodeBase64(input), 'uint8')';
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
function output = base64encode(input)
|
||||
import jsonlab.*
|
||||
%BASE64ENCODE Encode a byte array using Base64 codec.
|
||||
%
|
||||
% output = base64encode(input)
|
||||
%
|
||||
% The function takes a char, int8, or uint8 array INPUT and returns Base64
|
||||
% encoded string OUTPUT. JAVA must be running to use this function. Note
|
||||
% that encoding doesn't preserve input dimensions.
|
||||
%
|
||||
% See also base64decode
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(uint8(input),1,'base64');
|
||||
return;
|
||||
end
|
||||
if(exist('OCTAVE_VERSION','builtin'))
|
||||
output = base64_encode(uint8(input));
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input), input = uint8(input); end
|
||||
|
||||
output = char(org.apache.commons.codec.binary.Base64.encodeBase64Chunked(input))';
|
||||
output = regexprep(output,'\r','');
|
||||
end
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Demonstration of Basic Utilities of JSONlab
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
rngstate = rand ('state');
|
||||
randseed=hex2dec('623F9A9E');
|
||||
clear data2json json2data
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a simple scalar value \n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=pi
|
||||
savejson('',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex number\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
clear i;
|
||||
data2json=1+2*i
|
||||
savejson('',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=magic(6);
|
||||
data2json=data2json(:,1:3)+data2json(:,4:6)*i
|
||||
savejson('',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% MATLAB special constants\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=[NaN Inf -Inf]
|
||||
savejson('specials',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a real sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sprand(10,10,0.1)
|
||||
savejson('sparse',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-data2json*i
|
||||
savejson('complex_sparse',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an all-zero sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse(2,3);
|
||||
savejson('all_zero_sparse',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([]);
|
||||
savejson('empty_sparse',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty 0-by-0 real matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=[];
|
||||
savejson('empty_0by0_real',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty 0-by-3 real matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=zeros(0,3);
|
||||
savejson('empty_0by3_real',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse real column vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([0,3,0,1,4]');
|
||||
savejson('sparse_column_vector',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse complex column vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-1i*data2json;
|
||||
savejson('complex_sparse_column_vector',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse real row vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([0,3,0,1,4]);
|
||||
savejson('sparse_row_vector',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse complex row vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-1i*data2json;
|
||||
savejson('complex_sparse_row_vector',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a structure\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=struct('name','Think Different','year',1997,'magic',magic(3),...
|
||||
'misfits',[Inf,NaN],'embedded',struct('left',true,'right',false))
|
||||
savejson('astruct',data2json,struct('ParseLogical',1))
|
||||
json2data=loadjson(ans)
|
||||
class(json2data.astruct.embedded.left)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a structure array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=struct('name','Nexus Prime','rank',9);
|
||||
data2json(2)=struct('name','Sentinel Prime','rank',9);
|
||||
data2json(3)=struct('name','Optimus Prime','rank',9);
|
||||
savejson('Supreme Commander',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a cell array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=cell(3,1);
|
||||
data2json{1}=struct('buzz',1.1,'rex',1.2,'bo',1.3,'hamm',2.0,'slink',2.1,'potato',2.2,...
|
||||
'woody',3.0,'sarge',3.1,'etch',4.0,'lenny',5.0,'squeeze',6.0,'wheezy',7.0);
|
||||
data2json{2}=struct('Ubuntu',['Kubuntu';'Xubuntu';'Lubuntu']);
|
||||
data2json{3}=[10.04,10.10,11.04,11.10]
|
||||
savejson('debian',data2json,struct('FloatFormat','%.2f'))
|
||||
json2data=loadjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% invalid field-name handling\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
json2data=loadjson('{"ValidName":1, "_InvalidName":2, ":Field:":3, "项目":"绝密"}')
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a 2D cell array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json={{1,{2,3}},{4,5},{6};{7},{8,9},{10}};
|
||||
savejson('data2json',data2json)
|
||||
json2data=loadjson(ans) % only savejson works for cell arrays, loadjson has issues
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a 2D struct array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=repmat(struct('idx',0,'data','structs'),[2,3])
|
||||
for i=1:6
|
||||
data2json(i).idx=i;
|
||||
end
|
||||
savejson('data2json',data2json)
|
||||
json2data=loadjson(ans)
|
||||
|
||||
rand ('state',rngstate);
|
||||
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Demonstration of Basic Utilities of JSONlab
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
rngstate = rand ('state');
|
||||
randseed=hex2dec('623F9A9E');
|
||||
clear data2json json2data
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a simple scalar value \n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=pi
|
||||
saveubjson('',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex number\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
clear i;
|
||||
data2json=1+2*i
|
||||
saveubjson('',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=magic(6);
|
||||
data2json=data2json(:,1:3)+data2json(:,4:6)*i
|
||||
saveubjson('',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% MATLAB special constants\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=[NaN Inf -Inf]
|
||||
saveubjson('specials',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a real sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sprand(10,10,0.1)
|
||||
saveubjson('sparse',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a complex sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-data2json*i
|
||||
saveubjson('complex_sparse',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an all-zero sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse(2,3);
|
||||
saveubjson('all_zero_sparse',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty sparse matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([]);
|
||||
saveubjson('empty_sparse',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty 0-by-0 real matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=[];
|
||||
saveubjson('empty_0by0_real',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% an empty 0-by-3 real matrix\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=zeros(0,3);
|
||||
saveubjson('empty_0by3_real',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse real column vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([0,3,0,1,4]');
|
||||
saveubjson('sparse_column_vector',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse complex column vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-1i*data2json;
|
||||
saveubjson('complex_sparse_column_vector',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse real row vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=sparse([0,3,0,1,4]);
|
||||
saveubjson('sparse_row_vector',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a sparse complex row vector\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=data2json-1i*data2json;
|
||||
saveubjson('complex_sparse_row_vector',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a structure\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=struct('name','Think Different','year',1997,'magic',magic(3),...
|
||||
'misfits',[Inf,NaN],'embedded',struct('left',true,'right',false))
|
||||
saveubjson('astruct',data2json,struct('ParseLogical',1))
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a structure array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=struct('name','Nexus Prime','rank',9);
|
||||
data2json(2)=struct('name','Sentinel Prime','rank',9);
|
||||
data2json(3)=struct('name','Optimus Prime','rank',9);
|
||||
saveubjson('Supreme Commander',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a cell array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=cell(3,1);
|
||||
data2json{1}=struct('buzz',1.1,'rex',1.2,'bo',1.3,'hamm',2.0,'slink',2.1,'potato',2.2,...
|
||||
'woody',3.0,'sarge',3.1,'etch',4.0,'lenny',5.0,'squeeze',6.0,'wheezy',7.0);
|
||||
data2json{2}=struct('Ubuntu',['Kubuntu';'Xubuntu';'Lubuntu']);
|
||||
data2json{3}=[10.04,10.10,11.04,11.10]
|
||||
saveubjson('debian',data2json,struct('FloatFormat','%.2f'))
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% invalid field-name handling\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
json2data=loadubjson(saveubjson('',loadjson('{"ValidName":1, "_InvalidName":2, ":Field:":3, "项目":"绝密"}')))
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a 2D cell array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json={{1,{2,3}},{4,5},{6};{7},{8,9},{10}};
|
||||
saveubjson('data2json',data2json)
|
||||
json2data=loadubjson(ans) % only savejson works for cell arrays, loadjson has issues
|
||||
|
||||
fprintf(1,'\n%%=================================================\n')
|
||||
fprintf(1,'%% a 2D struct array\n')
|
||||
fprintf(1,'%%=================================================\n\n')
|
||||
|
||||
data2json=repmat(struct('idx',0,'data','structs'),[2,3])
|
||||
for i=1:6
|
||||
data2json(i).idx=i;
|
||||
end
|
||||
saveubjson('data2json',data2json)
|
||||
json2data=loadubjson(ans)
|
||||
|
||||
rand ('state',rngstate);
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"age": 25,
|
||||
"address":
|
||||
{
|
||||
"streetAddress": "21 2nd Street",
|
||||
"city": "New York",
|
||||
"state": "NY",
|
||||
"postalCode": "10021"
|
||||
},
|
||||
"phoneNumber":
|
||||
[
|
||||
{
|
||||
"type": "home",
|
||||
"number": "212 555-1234"
|
||||
},
|
||||
{
|
||||
"type": "fax",
|
||||
"number": "646 555-4567"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"glossary": {
|
||||
"title": "example glossary",
|
||||
"GlossDiv": {
|
||||
"title": "S",
|
||||
"GlossList": {
|
||||
"GlossEntry": {
|
||||
"ID": "SGML",
|
||||
"SortAs": "SGML",
|
||||
"GlossTerm": "Standard Generalized Markup Language",
|
||||
"Acronym": "SGML",
|
||||
"Abbrev": "ISO 8879:1986",
|
||||
"GlossDef": {
|
||||
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||
"GlossSeeAlso": ["GML", "XML"]
|
||||
},
|
||||
"GlossSee": "markup"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{"menu": {
|
||||
"id": "file",
|
||||
"value": "_&File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{"value": "_&New", "onclick": "CreateNewDoc(\"'\\\"Untitled\\\"'\")"},
|
||||
{"value": "_&Open", "onclick": "OpenDoc()"},
|
||||
{"value": "_&Close", "onclick": "CloseDoc()"}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
[
|
||||
{
|
||||
"sample" : {
|
||||
"rho" : 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"sample" : {
|
||||
"rho" : 2
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
"_ArrayType_" : "double",
|
||||
"_ArraySize_" : [1,2],
|
||||
"_ArrayData_" : [1,0]
|
||||
},
|
||||
{
|
||||
"_ArrayType_" : "double",
|
||||
"_ArraySize_" : [1,2],
|
||||
"_ArrayData_" : [1,1]
|
||||
},
|
||||
{
|
||||
"_ArrayType_" : "double",
|
||||
"_ArraySize_" : [1,2],
|
||||
"_ArrayData_" : [1,2]
|
||||
}
|
||||
],
|
||||
[
|
||||
"Paper",
|
||||
"Scissors",
|
||||
"Stone"
|
||||
],
|
||||
["a", "b\\", "c\"","d\\\"","e\"[","f\\\"[","g[\\","h[\\\""]
|
||||
]
|
||||
|
|
@ -0,0 +1,671 @@
|
|||
|
||||
< M A T L A B (R) >
|
||||
Copyright 1984-2010 The MathWorks, Inc.
|
||||
Version 7.11.0.584 (R2010b) 64-bit (glnxa64)
|
||||
August 16, 2010
|
||||
|
||||
|
||||
To get started, type one of these: helpwin, helpdesk, or demo.
|
||||
For product information, visit www.mathworks.com.
|
||||
|
||||
>> >> >> >> >> >> >> >> >>
|
||||
%=================================================
|
||||
>> % a simple scalar value
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
3.1416
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
[3.141592654]
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
3.1416
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex number
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
data2json =
|
||||
|
||||
1.0000 + 2.0000i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [1,1],
|
||||
"_ArrayIsComplex_": 1,
|
||||
"_ArrayData_": [1,2]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
1.0000 + 2.0000i
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
data2json =
|
||||
|
||||
35.0000 +26.0000i 1.0000 +19.0000i 6.0000 +24.0000i
|
||||
3.0000 +21.0000i 32.0000 +23.0000i 7.0000 +25.0000i
|
||||
31.0000 +22.0000i 9.0000 +27.0000i 2.0000 +20.0000i
|
||||
8.0000 +17.0000i 28.0000 +10.0000i 33.0000 +15.0000i
|
||||
30.0000 +12.0000i 5.0000 +14.0000i 34.0000 +16.0000i
|
||||
4.0000 +13.0000i 36.0000 +18.0000i 29.0000 +11.0000i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [6,3],
|
||||
"_ArrayIsComplex_": 1,
|
||||
"_ArrayData_": [
|
||||
[35,26],
|
||||
[3,21],
|
||||
[31,22],
|
||||
[8,17],
|
||||
[30,12],
|
||||
[4,13],
|
||||
[1,19],
|
||||
[32,23],
|
||||
[9,27],
|
||||
[28,10],
|
||||
[5,14],
|
||||
[36,18],
|
||||
[6,24],
|
||||
[7,25],
|
||||
[2,20],
|
||||
[33,15],
|
||||
[34,16],
|
||||
[29,11]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
35.0000 +26.0000i 1.0000 +19.0000i 6.0000 +24.0000i
|
||||
3.0000 +21.0000i 32.0000 +23.0000i 7.0000 +25.0000i
|
||||
31.0000 +22.0000i 9.0000 +27.0000i 2.0000 +20.0000i
|
||||
8.0000 +17.0000i 28.0000 +10.0000i 33.0000 +15.0000i
|
||||
30.0000 +12.0000i 5.0000 +14.0000i 34.0000 +16.0000i
|
||||
4.0000 +13.0000i 36.0000 +18.0000i 29.0000 +11.0000i
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % MATLAB special constants
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
NaN Inf -Inf
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"specials": ["_NaN_","_Inf_","-_Inf_"]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
specials: [NaN Inf -Inf]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a real sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
(1,2) 0.6557
|
||||
(9,2) 0.7577
|
||||
(3,5) 0.8491
|
||||
(10,5) 0.7431
|
||||
(10,8) 0.3922
|
||||
(7,9) 0.6787
|
||||
(2,10) 0.0357
|
||||
(6,10) 0.9340
|
||||
(10,10) 0.6555
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"sparse": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [10,10],
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[1,2,0.6557406992],
|
||||
[9,2,0.7577401306],
|
||||
[3,5,0.8491293059],
|
||||
[10,5,0.7431324681],
|
||||
[10,8,0.3922270195],
|
||||
[7,9,0.6787351549],
|
||||
[2,10,0.03571167857],
|
||||
[6,10,0.9339932478],
|
||||
[10,10,0.6554778902]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse: [10x10 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
(1,2) 0.6557 - 0.6557i
|
||||
(9,2) 0.7577 - 0.7577i
|
||||
(3,5) 0.8491 - 0.8491i
|
||||
(10,5) 0.7431 - 0.7431i
|
||||
(10,8) 0.3922 - 0.3922i
|
||||
(7,9) 0.6787 - 0.6787i
|
||||
(2,10) 0.0357 - 0.0357i
|
||||
(6,10) 0.9340 - 0.9340i
|
||||
(10,10) 0.6555 - 0.6555i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"complex_sparse": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [10,10],
|
||||
"_ArrayIsComplex_": 1,
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[1,2,0.6557406992,-0.6557406992],
|
||||
[9,2,0.7577401306,-0.7577401306],
|
||||
[3,5,0.8491293059,-0.8491293059],
|
||||
[10,5,0.7431324681,-0.7431324681],
|
||||
[10,8,0.3922270195,-0.3922270195],
|
||||
[7,9,0.6787351549,-0.6787351549],
|
||||
[2,10,0.03571167857,-0.03571167857],
|
||||
[6,10,0.9339932478,-0.9339932478],
|
||||
[10,10,0.6554778902,-0.6554778902]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse: [10x10 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an all-zero sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"all_zero_sparse": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [2,3],
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
all_zero_sparse: [2x3 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"empty_sparse": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [0,0],
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_sparse: []
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty 0-by-0 real matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"empty_0by0_real": null
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_0by0_real: []
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty 0-by-3 real matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"empty_0by3_real": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [0,3],
|
||||
"_ArrayData_": null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_0by3_real: [0x3 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse real column vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"sparse_column_vector": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [5,1],
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[2,3],
|
||||
[4,1],
|
||||
[5,4]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse_column_vector: [5x1 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse complex column vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"complex_sparse_column_vector": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [5,1],
|
||||
"_ArrayIsComplex_": 1,
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[2,3,-3],
|
||||
[4,1,-1],
|
||||
[5,4,-4]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse_column_vector: [5x1 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse real row vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"sparse_row_vector": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [1,5],
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[2,3],
|
||||
[4,1],
|
||||
[5,4]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse_row_vector: [0 3 0 1 4]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse complex row vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"complex_sparse_row_vector": {
|
||||
"_ArrayType_": "double",
|
||||
"_ArraySize_": [1,5],
|
||||
"_ArrayIsComplex_": 1,
|
||||
"_ArrayIsSparse_": 1,
|
||||
"_ArrayData_": [
|
||||
[2,3,-3],
|
||||
[4,1,-1],
|
||||
[5,4,-4]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse_row_vector: [1x5 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a structure
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
name: 'Think Different'
|
||||
year: 1997
|
||||
magic: [3x3 double]
|
||||
misfits: [Inf NaN]
|
||||
embedded: [1x1 struct]
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"astruct": {
|
||||
"name": "Think Different",
|
||||
"year": 1997,
|
||||
"magic": [
|
||||
[8,1,6],
|
||||
[3,5,7],
|
||||
[4,9,2]
|
||||
],
|
||||
"misfits": ["_Inf_","_NaN_"],
|
||||
"embedded": {
|
||||
"left": true,
|
||||
"right": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
astruct: [1x1 struct]
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
logical
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a structure array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"Supreme Commander": [
|
||||
{
|
||||
"name": "Nexus Prime",
|
||||
"rank": 9
|
||||
},
|
||||
{
|
||||
"name": "Sentinel Prime",
|
||||
"rank": 9
|
||||
},
|
||||
{
|
||||
"name": "Optimus Prime",
|
||||
"rank": 9
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
Supreme_0x20_Commander: {[1x1 struct] [1x1 struct] [1x1 struct]}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a cell array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >> >> >>
|
||||
data2json =
|
||||
|
||||
[1x1 struct]
|
||||
[1x1 struct]
|
||||
[1x4 double]
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{
|
||||
"debian": [
|
||||
[
|
||||
{
|
||||
"buzz": 1.10,
|
||||
"rex": 1.20,
|
||||
"bo": 1.30,
|
||||
"hamm": 2.00,
|
||||
"slink": 2.10,
|
||||
"potato": 2.20,
|
||||
"woody": 3.00,
|
||||
"sarge": 3.10,
|
||||
"etch": 4.00,
|
||||
"lenny": 5.00,
|
||||
"squeeze": 6.00,
|
||||
"wheezy": 7.00
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"Ubuntu": [
|
||||
"Kubuntu",
|
||||
"Xubuntu",
|
||||
"Lubuntu"
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
[10.04,10.10,11.04,11.10]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
debian: {{1x1 cell} {1x1 cell} [10.0400 10.1000 11.0400 11.1000]}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % invalid field-name handling
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
json2data =
|
||||
|
||||
ValidName: 1
|
||||
x0x5F_InvalidName: 2
|
||||
x0x3A_Field_0x3A_: 3
|
||||
x0xE9A1B9__0xE79BAE_: '绝密'
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a 2D cell array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"data2json": [
|
||||
[
|
||||
[
|
||||
1,
|
||||
[
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
4,
|
||||
5
|
||||
],
|
||||
[
|
||||
6
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7
|
||||
],
|
||||
[
|
||||
8,
|
||||
9
|
||||
],
|
||||
[
|
||||
10
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
data2json: {{3x1 cell} {3x1 cell}}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a 2D struct array
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
2x3 struct array with fields:
|
||||
idx
|
||||
data
|
||||
|
||||
>> >>
|
||||
ans =
|
||||
|
||||
{
|
||||
"data2json": [
|
||||
[
|
||||
{
|
||||
"idx": 1,
|
||||
"data": "structs"
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"data": "structs"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"idx": 3,
|
||||
"data": "structs"
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"data": "structs"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"idx": 5,
|
||||
"data": "structs"
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"data": "structs"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
data2json: {{1x2 cell} {1x2 cell} {1x2 cell}}
|
||||
|
||||
>> >> >> >>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Regression Test Unit of loadjson and savejson
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
for i=1:4
|
||||
fname=sprintf('example%d.json',i);
|
||||
if(exist(fname,'file')==0) break; end
|
||||
fprintf(1,'===============================================\n>> %s\n',fname);
|
||||
json=savejson('data',loadjson(fname));
|
||||
fprintf(1,'%s\n',json);
|
||||
fprintf(1,'%s\n',savejson('data',loadjson(fname),'Compact',1));
|
||||
data=loadjson(json);
|
||||
savejson('data',data,'selftest.json');
|
||||
data=loadjson('selftest.json');
|
||||
end
|
||||
|
||||
for i=1:4
|
||||
fname=sprintf('example%d.json',i);
|
||||
if(exist(fname,'file')==0) break; end
|
||||
fprintf(1,'===============================================\n>> %s\n',fname);
|
||||
json=saveubjson('data',loadjson(fname));
|
||||
fprintf(1,'%s\n',json);
|
||||
data=loadubjson(json);
|
||||
savejson('',data);
|
||||
saveubjson('data',data,'selftest.ubj');
|
||||
data=loadubjson('selftest.ubj');
|
||||
end
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
|
||||
< M A T L A B (R) >
|
||||
Copyright 1984-2010 The MathWorks, Inc.
|
||||
Version 7.11.0.584 (R2010b) 64-bit (glnxa64)
|
||||
August 16, 2010
|
||||
|
||||
|
||||
To get started, type one of these: helpwin, helpdesk, or demo.
|
||||
For product information, visit www.mathworks.com.
|
||||
|
||||
>> >> >> >> >> ===============================================
|
||||
>> example1.json
|
||||
{
|
||||
"data": {
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"age": 25,
|
||||
"address": {
|
||||
"streetAddress": "21 2nd Street",
|
||||
"city": "New York",
|
||||
"state": "NY",
|
||||
"postalCode": "10021"
|
||||
},
|
||||
"phoneNumber": [
|
||||
{
|
||||
"type": "home",
|
||||
"number": "212 555-1234"
|
||||
},
|
||||
{
|
||||
"type": "fax",
|
||||
"number": "646 555-4567"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
{"data": {"firstName": "John","lastName": "Smith","age": 25,"address": {"streetAddress": "21 2nd Street","city": "New York","state": "NY","postalCode": "10021"},"phoneNumber": [{"type": "home","number": "212 555-1234"},{"type": "fax","number": "646 555-4567"}]}}
|
||||
|
||||
===============================================
|
||||
>> example2.json
|
||||
{
|
||||
"data": {
|
||||
"glossary": {
|
||||
"title": "example glossary",
|
||||
"GlossDiv": {
|
||||
"title": "S",
|
||||
"GlossList": {
|
||||
"GlossEntry": {
|
||||
"ID": "SGML",
|
||||
"SortAs": "SGML",
|
||||
"GlossTerm": "Standard Generalized Markup Language",
|
||||
"Acronym": "SGML",
|
||||
"Abbrev": "ISO 8879:1986",
|
||||
"GlossDef": {
|
||||
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||
"GlossSeeAlso": [
|
||||
"GML",
|
||||
"XML"
|
||||
]
|
||||
},
|
||||
"GlossSee": "markup"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{"data": {"glossary": {"title": "example glossary","GlossDiv": {"title": "S","GlossList": {"GlossEntry": {"ID": "SGML","SortAs": "SGML","GlossTerm": "Standard Generalized Markup Language","Acronym": "SGML","Abbrev": "ISO 8879:1986","GlossDef": {"para": "A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso": ["GML","XML"]},"GlossSee": "markup"}}}}}}
|
||||
|
||||
===============================================
|
||||
>> example3.json
|
||||
{
|
||||
"data": {
|
||||
"menu": {
|
||||
"id": "file",
|
||||
"value": "_&File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{
|
||||
"value": "_&New",
|
||||
"onclick": "CreateNewDoc(\"'\\\"Untitled\\\"'\")"
|
||||
},
|
||||
{
|
||||
"value": "_&Open",
|
||||
"onclick": "OpenDoc()"
|
||||
},
|
||||
{
|
||||
"value": "_&Close",
|
||||
"onclick": "CloseDoc()"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{"data": {"menu": {"id": "file","value": "_&File","popup": {"menuitem": [{"value": "_&New","onclick": "CreateNewDoc(\"'\\\"Untitled\\\"'\")"},{"value": "_&Open","onclick": "OpenDoc()"},{"value": "_&Close","onclick": "CloseDoc()"}]}}}}
|
||||
|
||||
===============================================
|
||||
>> example4.json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"sample": {
|
||||
"rho": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"sample": {
|
||||
"rho": 2
|
||||
}
|
||||
},
|
||||
[
|
||||
[1,0],
|
||||
[1,1],
|
||||
[1,2]
|
||||
],
|
||||
[
|
||||
"Paper",
|
||||
"Scissors",
|
||||
"Stone"
|
||||
],
|
||||
[
|
||||
"a",
|
||||
"b\\",
|
||||
"c\"",
|
||||
"d\\\"",
|
||||
"e\"[",
|
||||
"f\\\"[",
|
||||
"g[\\",
|
||||
"h[\\\""
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
{"data": [{"sample": {"rho": 1}},{"sample": {"rho": 2}},[[1,0],[1,1],[1,2]],["Paper","Scissors","Stone"],["a","b\\","c\"","d\\\"","e\"[","f\\\"[","g[\\","h[\\\""]]}
|
||||
|
||||
>> >> ===============================================
|
||||
>> example1.json
|
||||
{Udata{U firstNameSUJohnUlastNameSUSmithUageiUaddress{U
streetAddressSU
21 2nd StreetUcitySUNew YorkUstateSUNYU
|
||||
postalCodeSU10021}UphoneNumber[{UtypeSUhomeUnumberSU212 555-1234}{UtypeSUfaxUnumberSU646 555-4567}]}}
|
||||
===============================================
|
||||
>> example2.json
|
||||
{Udata{Uglossary{UtitleSUexample glossaryUGlossDiv{UtitleCSU GlossList{U
|
||||
GlossEntry{UIDSUSGMLUSortAsSUSGMLU GlossTermSU$Standard Generalized Markup LanguageUAcronymSUSGMLUAbbrevSU
ISO 8879:1986UGlossDef{UparaSUHA meta-markup language, used to create markup languages such as DocBook.UGlossSeeAlso[SUGMLSUXML]}UGlossSeeSUmarkup}}}}}}
|
||||
===============================================
|
||||
>> example3.json
|
||||
{Udata{Umenu{UidSUfileUvalueSU_&FileUpopup{Umenuitem[{UvalueSU_&NewUonclickSUCreateNewDoc("'\"Untitled\"'")}{UvalueSU_&OpenUonclickSU OpenDoc()}{UvalueSU_&CloseUonclickSU
|
||||
CloseDoc()}]}}}}
|
||||
===============================================
|
||||
>> example4.json
|
||||
{Udata[{Usample{Urhoi}}{Usample{Urhoi}}[[$i#U[$i#U[$i#U][SUPaperSUScissorsSUStone][CaSUb\SUc"SUd\"SUe"[SUf\"[SUg[\SUh[\"]]}
|
||||
>>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Benchmarking processing speed of savejson and loadjson
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
datalen=[1e3 1e4 1e5 1e6];
|
||||
len=length(datalen);
|
||||
tsave=zeros(len,1);
|
||||
tload=zeros(len,1);
|
||||
for i=1:len
|
||||
tic;
|
||||
json=savejson('data',struct('d1',rand(datalen(i),3),'d2',rand(datalen(i),3)>0.5));
|
||||
tsave(i)=toc;
|
||||
data=loadjson(json);
|
||||
tload(i)=toc-tsave(i);
|
||||
fprintf(1,'matrix size: %d\n',datalen(i));
|
||||
end
|
||||
|
||||
loglog(datalen,tsave,'o-',datalen,tload,'r*-');
|
||||
legend('savejson runtime (s)','loadjson runtime (s)');
|
||||
xlabel('array size');
|
||||
ylabel('running time (s)');
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
|
||||
< M A T L A B (R) >
|
||||
Copyright 1984-2010 The MathWorks, Inc.
|
||||
Version 7.11.0.584 (R2010b) 64-bit (glnxa64)
|
||||
August 16, 2010
|
||||
|
||||
|
||||
To get started, type one of these: helpwin, helpdesk, or demo.
|
||||
For product information, visit www.mathworks.com.
|
||||
|
||||
>> >> >> >> >> >> >> >> >>
|
||||
%=================================================
|
||||
>> % a simple scalar value
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
3.1416
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
[D@ !ûTD-]
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
[3.1416]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex number
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
data2json =
|
||||
|
||||
1.0000 + 2.0000i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsComplex_TU_ArrayData_[$i#U}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
1.0000 + 2.0000i
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
data2json =
|
||||
|
||||
35.0000 +26.0000i 1.0000 +19.0000i 6.0000 +24.0000i
|
||||
3.0000 +21.0000i 32.0000 +23.0000i 7.0000 +25.0000i
|
||||
31.0000 +22.0000i 9.0000 +27.0000i 2.0000 +20.0000i
|
||||
8.0000 +17.0000i 28.0000 +10.0000i 33.0000 +15.0000i
|
||||
30.0000 +12.0000i 5.0000 +14.0000i 34.0000 +16.0000i
|
||||
4.0000 +13.0000i 36.0000 +18.0000i 29.0000 +11.0000i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsComplex_TU_ArrayData_[$i#[$U#U# $!"
|
||||
}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
35.0000 +26.0000i 1.0000 +19.0000i 6.0000 +24.0000i
|
||||
3.0000 +21.0000i 32.0000 +23.0000i 7.0000 +25.0000i
|
||||
31.0000 +22.0000i 9.0000 +27.0000i 2.0000 +20.0000i
|
||||
8.0000 +17.0000i 28.0000 +10.0000i 33.0000 +15.0000i
|
||||
30.0000 +12.0000i 5.0000 +14.0000i 34.0000 +16.0000i
|
||||
4.0000 +13.0000i 36.0000 +18.0000i 29.0000 +11.0000i
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % MATLAB special constants
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
NaN Inf -Inf
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{Uspecials[$D#Uÿø ð ÿð }
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
specials: [NaN Inf -Inf]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a real sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
(1,2) 0.6557
|
||||
(9,2) 0.7577
|
||||
(3,5) 0.8491
|
||||
(10,5) 0.7431
|
||||
(10,8) 0.3922
|
||||
(7,9) 0.6787
|
||||
(2,10) 0.0357
|
||||
(6,10) 0.9340
|
||||
(10,10) 0.6555
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{Usparse{U_ArrayType_SUdoubleU_ArraySize_[$U#U
|
||||
|
||||
U_ArrayIsSparse_TU_ArrayData_[$D#[$U#U ?ð @" @ @$ @$ @ @ @ @$ @ @ @ @ @ @" @$ @$ @$ ?äûÓë12?è?h:öl;?ë,8Ù±?çǽ½æ'#?Ù?[`o?å¸2ÉNé?¢HÍpà?íãEι¶P?äù¬Ä² ¶}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse: [10x10 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a complex sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
(1,2) 0.6557 - 0.6557i
|
||||
(9,2) 0.7577 - 0.7577i
|
||||
(3,5) 0.8491 - 0.8491i
|
||||
(10,5) 0.7431 - 0.7431i
|
||||
(10,8) 0.3922 - 0.3922i
|
||||
(7,9) 0.6787 - 0.6787i
|
||||
(2,10) 0.0357 - 0.0357i
|
||||
(6,10) 0.9340 - 0.9340i
|
||||
(10,10) 0.6555 - 0.6555i
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{Ucomplex_sparse{U_ArrayType_SUdoubleU_ArraySize_[$U#U
|
||||
|
||||
U_ArrayIsComplex_TU_ArrayIsSparse_TU_ArrayData_[$D#[$U#U ?ð @" @ @$ @$ @ @ @ @$ @ @ @ @ @ @" @$ @$ @$ ?äûÓë12?è?h:öl;?ë,8Ù±?çǽ½æ'#?Ù?[`o?å¸2ÉNé?¢HÍpà?íãEι¶P?äù¬Ä² ¶¿äûÓë12¿è?h:öl;¿ë,8Ù±¿çǽ½æ'#¿Ù?[`o¿å¸2ÉNé¿¢HÍpà¿íãEι¶P¿äù¬Ä² ¶}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse: [10x10 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an all-zero sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Uall_zero_sparse{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsSparse_TU_ArrayData_Z}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
all_zero_sparse: [2x3 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty sparse matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Uempty_sparseZ}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_sparse: []
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty 0-by-0 real matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Uempty_0by0_realZ}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_0by0_real: []
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % an empty 0-by-3 real matrix
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Uempty_0by3_realZ}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
empty_0by3_real: []
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse real column vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Usparse_column_vector{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsSparse_TU_ArrayData_[$i#[$U#U}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse_column_vector: [5x1 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse complex column vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Ucomplex_sparse_column_vector{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsComplex_TU_ArrayIsSparse_TU_ArrayData_[$i#[$U#Uýÿü}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse_column_vector: [5x1 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse real row vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Usparse_row_vector{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsSparse_TU_ArrayData_[$i#[$U#U}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
sparse_row_vector: [0 3 0 1 4]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a sparse complex row vector
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{Ucomplex_sparse_row_vector{U_ArrayType_SUdoubleU_ArraySize_[$U#UU_ArrayIsComplex_TU_ArrayIsSparse_TU_ArrayData_[$i#[$U#Uýÿü}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
complex_sparse_row_vector: [1x5 double]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a structure
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
name: 'Think Different'
|
||||
year: 1997
|
||||
magic: [3x3 double]
|
||||
misfits: [Inf NaN]
|
||||
embedded: [1x1 struct]
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{Uastruct{UnameSUThink DifferentUyearIÍUmagic[$i#[$U#U Umisfits[$D#Uð ÿø Uembedded{UleftTUrightF}}}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
astruct: [1x1 struct]
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a structure array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >> >> >>
|
||||
ans =
|
||||
|
||||
{USupreme Commander[{UnameSUNexus PrimeUranki }{UnameSUSentinel PrimeUranki }{UnameSU
Optimus PrimeUranki }]}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
Supreme_0x20_Commander: {[1x1 struct] [1x1 struct] [1x1 struct]}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a cell array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >> >> >>
|
||||
data2json =
|
||||
|
||||
[1x1 struct]
|
||||
[1x1 struct]
|
||||
[1x4 double]
|
||||
|
||||
>>
|
||||
ans =
|
||||
|
||||
{Udebian[[{UbuzzD?ñUrexD?ó333333UboD?ôÌÌÌÌÌÍUhammiUslinkD@ ÌÌÌÌÌÍUpotatoD@UwoodyiUsargeD@ÌÌÌÌÌÍUetchiUlennyiUsqueezeiUwheezyi}{UUbuntu[SUKubuntuSUXubuntuSULubuntu]}[$D#U@$záG®@$333333@&záG®@&333333]]}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
debian: {{1x3 cell}}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % invalid field-name handling
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
json2data =
|
||||
|
||||
ValidName: 1
|
||||
x0x5F_InvalidName: 2
|
||||
x0x3A_Field_0x3A_: 3
|
||||
x0xEFBFBD__0xEFBFBD_: '绝密'
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a 2D cell array
|
||||
>> %=================================================
|
||||
|
||||
>> >> >>
|
||||
ans =
|
||||
|
||||
{U data2json[[[[i][[i][i]]][[i]]][[[i][i]][[i][i ]]][[[i]][[i
|
||||
]]]]}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
data2json: {{1x2 cell} {1x2 cell} {1x2 cell}}
|
||||
|
||||
>> >>
|
||||
%=================================================
|
||||
>> % a 2D struct array
|
||||
>> %=================================================
|
||||
|
||||
>> >>
|
||||
data2json =
|
||||
|
||||
2x3 struct array with fields:
|
||||
idx
|
||||
data
|
||||
|
||||
>> >>
|
||||
ans =
|
||||
|
||||
{U data2json[[{UidxiUdataSUstructs}{UidxiUdataSUstructs}][{UidxiUdataSUstructs}{UidxiUdataSUstructs}][{UidxiUdataSUstructs}{UidxiUdataSUstructs}]]}
|
||||
|
||||
>>
|
||||
json2data =
|
||||
|
||||
data2json: {{1x2 cell} {1x2 cell} {1x2 cell}}
|
||||
|
||||
>> >> >> >>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
function output = gzipdecode(input)
|
||||
import jsonlab.*
|
||||
%GZIPDECODE Decompress input bytes using GZIP.
|
||||
%
|
||||
% output = gzipdecode(input)
|
||||
%
|
||||
% The function takes a compressed byte array INPUT and returns inflated
|
||||
% bytes OUTPUT. The INPUT is a result of GZIPENCODE function. The OUTPUT
|
||||
% is always an 1-by-N uint8 array. JAVA must be enabled to use the function.
|
||||
%
|
||||
% See also gzipencode typecast
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(uint8(input),0,'gzip');
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input)
|
||||
warning('gzipdecode:inputTypeMismatch', ...
|
||||
'Input is char, but treated as uint8.');
|
||||
input = uint8(input);
|
||||
end
|
||||
if ~isa(input, 'int8') && ~isa(input, 'uint8')
|
||||
error('Input must be either int8 or uint8.');
|
||||
end
|
||||
|
||||
gzip = java.util.zip.GZIPInputStream(java.io.ByteArrayInputStream(input));
|
||||
buffer = java.io.ByteArrayOutputStream();
|
||||
org.apache.commons.io.IOUtils.copy(gzip, buffer);
|
||||
gzip.close();
|
||||
output = typecast(buffer.toByteArray(), 'uint8')';
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
function output = gzipencode(input)
|
||||
import jsonlab.*
|
||||
%GZIPENCODE Compress input bytes with GZIP.
|
||||
%
|
||||
% output = gzipencode(input)
|
||||
%
|
||||
% The function takes a char, int8, or uint8 array INPUT and returns
|
||||
% compressed bytes OUTPUT as a uint8 array. Note that the compression
|
||||
% doesn't preserve input dimensions. JAVA must be enabled to use the
|
||||
% function.
|
||||
%
|
||||
% See also gzipdecode typecast
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(uint8(input),1,'gzip');
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input), input = uint8(input); end
|
||||
if ~isa(input, 'int8') && ~isa(input, 'uint8')
|
||||
error('Input must be either char, int8 or uint8.');
|
||||
end
|
||||
|
||||
buffer = java.io.ByteArrayOutputStream();
|
||||
gzip = java.util.zip.GZIPOutputStream(buffer);
|
||||
gzip.write(input, 0, numel(input));
|
||||
gzip.close();
|
||||
output = typecast(buffer.toByteArray(), 'uint8')';
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
function val=jsonopt(key,default,varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% val=jsonopt(key,default,optstruct)
|
||||
%
|
||||
% setting options based on a struct. The struct can be produced
|
||||
% by varargin2struct from a list of 'param','value' pairs
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
%
|
||||
% $Id: loadjson.m 371 2012-06-20 12:43:06Z fangq $
|
||||
%
|
||||
% input:
|
||||
% key: a string with which one look up a value from a struct
|
||||
% default: if the key does not exist, return default
|
||||
% optstruct: a struct where each sub-field is a key
|
||||
%
|
||||
% output:
|
||||
% val: if key exists, val=optstruct.key; otherwise val=default
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
val=default;
|
||||
if(nargin<=2) return; end
|
||||
opt=varargin{1};
|
||||
if(isstruct(opt))
|
||||
if(isfield(opt,key))
|
||||
val=getfield(opt,key);
|
||||
elseif(isfield(opt,lower(key)))
|
||||
val=getfield(opt,lower(key));
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
Copyright (c) 2019, Qianqian Fang
|
||||
Copyright (c) 2009, Nedialko
|
||||
Copyright (c) 2016, The MathWorks, Inc.
|
||||
Copyright (c) 2011, François Glineur
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
* Neither the name of the The MathWorks, Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
* In all cases, the software is, and all modifications and derivatives of the
|
||||
software shall be, licensed to you solely for use in conjunction with
|
||||
MathWorks products and service offerings.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,537 @@
|
|||
function data = loadjson(fname,varargin)
|
||||
%
|
||||
% data=loadjson(fname,opt)
|
||||
% or
|
||||
% data=loadjson(fname,'param1',value1,'param2',value2,...)
|
||||
%
|
||||
% parse a JSON (JavaScript Object Notation) file or string
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
% created on 2011/09/09, including previous works from
|
||||
%
|
||||
% Nedialko Krouchev: http://www.mathworks.com/matlabcentral/fileexchange/25713
|
||||
% created on 2009/11/02
|
||||
% François Glineur: http://www.mathworks.com/matlabcentral/fileexchange/23393
|
||||
% created on 2009/03/22
|
||||
% Joel Feenstra:
|
||||
% http://www.mathworks.com/matlabcentral/fileexchange/20565
|
||||
% created on 2008/07/03
|
||||
%
|
||||
% $Id$
|
||||
%
|
||||
% input:
|
||||
% fname: input file name, if fname contains "{}" or "[]", fname
|
||||
% will be interpreted as a JSON string
|
||||
% opt: a struct to store parsing options, opt can be replaced by
|
||||
% a list of ('param',value) pairs - the param string is equivallent
|
||||
% to a field in opt. opt can have the following
|
||||
% fields (first in [.|.] is the default)
|
||||
%
|
||||
% opt.SimplifyCell [0|1]: if set to 1, loadjson will call cell2mat
|
||||
% for each element of the JSON data, and group
|
||||
% arrays based on the cell2mat rules.
|
||||
% opt.FastArrayParser [1|0 or integer]: if set to 1, use a
|
||||
% speed-optimized array parser when loading an
|
||||
% array object. The fast array parser may
|
||||
% collapse block arrays into a single large
|
||||
% array similar to rules defined in cell2mat; 0 to
|
||||
% use a legacy parser; if set to a larger-than-1
|
||||
% value, this option will specify the minimum
|
||||
% dimension to enable the fast array parser. For
|
||||
% example, if the input is a 3D array, setting
|
||||
% FastArrayParser to 1 will return a 3D array;
|
||||
% setting to 2 will return a cell array of 2D
|
||||
% arrays; setting to 3 will return to a 2D cell
|
||||
% array of 1D vectors; setting to 4 will return a
|
||||
% 3D cell array.
|
||||
% opt.ShowProgress [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
% opt.ParseStringArray [0|1]: if set to 1, loadjson displays a progress bar.
|
||||
%
|
||||
% output:
|
||||
% dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
% and [...] are converted to arrays
|
||||
%
|
||||
% examples:
|
||||
% dat=loadjson('{"obj":{"string":"value","array":[1,2,3]}}')
|
||||
% dat=loadjson(['examples' filesep 'example1.json'])
|
||||
% dat=loadjson(['examples' filesep 'example1.json'],'SimplifyCell',1)
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
import jsonlab.*
|
||||
|
||||
global pos index_esc isoct arraytoken
|
||||
|
||||
if(regexp(fname,'^\s*(?:\[.*\])|(?:\{.*\})\s*$','once'))
|
||||
string=fname;
|
||||
elseif(exist(fname,'file'))
|
||||
try
|
||||
string = fileread(fname);
|
||||
catch
|
||||
try
|
||||
string = urlread(['file://',fname]);
|
||||
catch
|
||||
string = urlread(['file://',fullfile(pwd,fname)]);
|
||||
end
|
||||
end
|
||||
else
|
||||
error('input file does not exist');
|
||||
end
|
||||
|
||||
pos = 1; len = length(string); inStr = string;
|
||||
isoct=exist('OCTAVE_VERSION','builtin');
|
||||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
|
||||
jstr=regexprep(inStr,'\\\\',' ');
|
||||
escquote=regexp(jstr,'\\"');
|
||||
arraytoken=sort([arraytoken escquote]);
|
||||
|
||||
% String delimiters and escape chars identified to improve speed:
|
||||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]');
|
||||
index_esc = 1;
|
||||
|
||||
opt=varargin2struct(varargin{:});
|
||||
|
||||
if(jsonopt('ShowProgress',0,opt)==1)
|
||||
opt.progressbar_=waitbar(0,'loading ...');
|
||||
end
|
||||
jsoncount=1;
|
||||
while pos <= len
|
||||
switch(next_char(inStr))
|
||||
case '{'
|
||||
data{jsoncount} = parse_object(inStr, esc, opt);
|
||||
case '['
|
||||
data{jsoncount} = parse_array(inStr, esc, opt);
|
||||
otherwise
|
||||
error_pos('Outer level structure must be an object or an array',inStr);
|
||||
end
|
||||
jsoncount=jsoncount+1;
|
||||
end % while
|
||||
|
||||
jsoncount=length(data);
|
||||
if(jsoncount==1 && iscell(data))
|
||||
data=data{1};
|
||||
end
|
||||
|
||||
if(isfield(opt,'progressbar_'))
|
||||
close(opt.progressbar_);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function object = parse_object(inStr, esc, varargin)
|
||||
import jsonlab.*
|
||||
parse_char(inStr, '{');
|
||||
object = [];
|
||||
if next_char(inStr) ~= '}'
|
||||
while 1
|
||||
str = parseStr(inStr, esc, varargin{:});
|
||||
if isempty(str)
|
||||
error_pos('Name of value at position %d cannot be empty',inStr);
|
||||
end
|
||||
parse_char(inStr, ':');
|
||||
val = parse_value(inStr, esc, varargin{:});
|
||||
object.(valid_field(str))=val;
|
||||
if next_char(inStr) == '}'
|
||||
break;
|
||||
end
|
||||
parse_char(inStr, ',');
|
||||
end
|
||||
end
|
||||
parse_char(inStr, '}');
|
||||
if(isstruct(object))
|
||||
object=struct2jdata(object);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function object = parse_array(inStr, esc, varargin) % JSON array is written in row-major order
|
||||
import jsonlab.*
|
||||
global pos isoct
|
||||
parse_char(inStr, '[');
|
||||
object = cell(0, 1);
|
||||
dim2=[];
|
||||
arraydepth=jsonopt('JSONLAB_ArrayDepth_',1,varargin{:});
|
||||
pbar=-1;
|
||||
if(isfield(varargin{1},'progressbar_'))
|
||||
pbar=varargin{1}.progressbar_;
|
||||
end
|
||||
|
||||
if next_char(inStr) ~= ']'
|
||||
if(jsonopt('FastArrayParser',1,varargin{:})>=1 && arraydepth>=jsonopt('FastArrayParser',1,varargin{:}))
|
||||
[endpos, e1l, e1r]=matching_bracket(inStr,pos);
|
||||
arraystr=['[' inStr(pos:endpos)];
|
||||
arraystr=regexprep(arraystr,'"_NaN_"','NaN');
|
||||
arraystr=regexprep(arraystr,'"([-+]*)_Inf_"','$1Inf');
|
||||
arraystr(arraystr==sprintf('\n'))=[];
|
||||
arraystr(arraystr==sprintf('\r'))=[];
|
||||
%arraystr=regexprep(arraystr,'\s*,',','); % this is slow,sometimes needed
|
||||
if(~isempty(e1l) && ~isempty(e1r)) % the array is in 2D or higher D
|
||||
astr=inStr((e1l+1):(e1r-1));
|
||||
astr=regexprep(astr,'"_NaN_"','NaN');
|
||||
astr=regexprep(astr,'"([-+]*)_Inf_"','$1Inf');
|
||||
astr(astr==sprintf('\n'))=[];
|
||||
astr(astr==sprintf('\r'))=[];
|
||||
astr(astr==' ')='';
|
||||
if(isempty(find(astr=='[', 1))) % array is 2D
|
||||
dim2=length(sscanf(astr,'%f,',[1 inf]));
|
||||
end
|
||||
else % array is 1D
|
||||
astr=arraystr(2:end-1);
|
||||
astr(astr==' ')='';
|
||||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',[1,inf]);
|
||||
if(nextidx>=length(astr)-1)
|
||||
object=obj;
|
||||
pos=endpos;
|
||||
parse_char(inStr, ']');
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
try
|
||||
if(~isempty(dim2))
|
||||
astr=arraystr;
|
||||
astr(astr=='[')='';
|
||||
astr(astr==']')='';
|
||||
astr=regexprep(astr,'\s*$','');
|
||||
astr(astr==' ')='';
|
||||
[obj, count, errmsg, nextidx]=sscanf(astr,'%f,',inf);
|
||||
if(nextidx>=length(astr)-1)
|
||||
object=reshape(obj,dim2,numel(obj)/dim2)';
|
||||
pos=endpos;
|
||||
parse_char(inStr, ']');
|
||||
if(pbar>0)
|
||||
waitbar(pos/length(inStr),pbar,'loading ...');
|
||||
end
|
||||
return;
|
||||
end
|
||||
end
|
||||
arraystr=regexprep(arraystr,'\]\s*,','];');
|
||||
catch
|
||||
end
|
||||
else
|
||||
arraystr='[';
|
||||
end
|
||||
try
|
||||
arraystr=regexprep(arraystr,'^\s*\[','{','once');
|
||||
arraystr=regexprep(arraystr,'\]\s*$','}','once');
|
||||
if(isoct && regexp(arraystr,'"','once'))
|
||||
error('Octave eval can produce empty cells for JSON-like input');
|
||||
end
|
||||
if(regexp(arraystr,':','once'))
|
||||
error('One can not use MATLAB-like ":" construct inside a JSON array');
|
||||
end
|
||||
if(jsonopt('ParseStringArray',0,varargin{:})==0)
|
||||
arraystr=regexprep(arraystr,'\"','''');
|
||||
end
|
||||
object=eval(arraystr);
|
||||
if(iscell(object))
|
||||
object=cellfun(@unescapejsonstring,object,'UniformOutput',false);
|
||||
end
|
||||
pos=endpos;
|
||||
catch
|
||||
while 1
|
||||
newopt=varargin2struct(varargin{:},'JSONLAB_ArrayDepth_',arraydepth+1);
|
||||
val = parse_value(inStr, esc, newopt);
|
||||
object{end+1} = val;
|
||||
if next_char(inStr) == ']'
|
||||
break;
|
||||
end
|
||||
parse_char(inStr, ',');
|
||||
end
|
||||
end
|
||||
end
|
||||
if(jsonopt('SimplifyCell',0,varargin{:})==1)
|
||||
try
|
||||
oldobj=object;
|
||||
object=cell2mat(object')';
|
||||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
|
||||
object=oldobj;
|
||||
elseif(size(object,1)>1 && ismatrix(object))
|
||||
object=object';
|
||||
end
|
||||
catch
|
||||
end
|
||||
end
|
||||
parse_char(inStr, ']');
|
||||
|
||||
if(pbar>0)
|
||||
waitbar(pos/length(inStr),pbar,'loading ...');
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function parse_char(inStr, c)
|
||||
import jsonlab.*
|
||||
global pos
|
||||
pos=skip_whitespace(pos, inStr);
|
||||
if pos > length(inStr) || inStr(pos) ~= c
|
||||
error_pos(sprintf('Expected %c at position %%d', c),inStr);
|
||||
else
|
||||
pos = pos + 1;
|
||||
pos=skip_whitespace(pos, inStr);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function c = next_char(inStr)
|
||||
import jsonlab.*
|
||||
global pos
|
||||
pos=skip_whitespace(pos, inStr);
|
||||
if pos > length(inStr)
|
||||
c = [];
|
||||
else
|
||||
c = inStr(pos);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function newpos=skip_whitespace(pos, inStr)
|
||||
import jsonlab.*
|
||||
newpos=pos;
|
||||
while newpos <= length(inStr) && isspace(inStr(newpos))
|
||||
newpos = newpos + 1;
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function str = parseStr(inStr, esc, varargin)
|
||||
import jsonlab.*
|
||||
global pos index_esc
|
||||
% len, ns = length(inStr), keyboard
|
||||
if inStr(pos) ~= '"'
|
||||
error_pos('String starting with " expected at position %d',inStr);
|
||||
else
|
||||
pos = pos + 1;
|
||||
end
|
||||
str = '';
|
||||
while pos <= length(inStr)
|
||||
while index_esc <= length(esc) && esc(index_esc) < pos
|
||||
index_esc = index_esc + 1;
|
||||
end
|
||||
if index_esc > length(esc)
|
||||
str = [str inStr(pos:end)];
|
||||
pos = length(inStr) + 1;
|
||||
break;
|
||||
else
|
||||
str = [str inStr(pos:esc(index_esc)-1)];
|
||||
pos = esc(index_esc);
|
||||
end
|
||||
nstr = length(str);
|
||||
switch inStr(pos)
|
||||
case '"'
|
||||
pos = pos + 1;
|
||||
if(~isempty(str))
|
||||
if(strcmp(str,'_Inf_'))
|
||||
str=Inf;
|
||||
elseif(strcmp(str,'-_Inf_'))
|
||||
str=-Inf;
|
||||
elseif(strcmp(str,'_NaN_'))
|
||||
str=NaN;
|
||||
end
|
||||
end
|
||||
return;
|
||||
case '\'
|
||||
if pos+1 > length(inStr)
|
||||
error_pos('End of file reached right after escape character',inStr);
|
||||
end
|
||||
pos = pos + 1;
|
||||
switch inStr(pos)
|
||||
case {'"' '\' '/'}
|
||||
str(nstr+1) = inStr(pos);
|
||||
pos = pos + 1;
|
||||
case {'b' 'f' 'n' 'r' 't'}
|
||||
str(nstr+1) = sprintf(['\' inStr(pos)]);
|
||||
pos = pos + 1;
|
||||
case 'u'
|
||||
if pos+4 > length(inStr)
|
||||
error_pos('End of file reached in escaped unicode character',inStr);
|
||||
end
|
||||
str(nstr+(1:6)) = inStr(pos-1:pos+4);
|
||||
pos = pos + 5;
|
||||
end
|
||||
otherwise % should never happen
|
||||
str(nstr+1) = inStr(pos);
|
||||
keyboard;
|
||||
pos = pos + 1;
|
||||
end
|
||||
end
|
||||
str=unescapejsonstring(str);
|
||||
error_pos('End of file while expecting end of inStr',inStr);
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function num = parse_number(inStr, varargin)
|
||||
import jsonlab.*
|
||||
global pos isoct
|
||||
currstr=inStr(pos:min(pos+30,end));
|
||||
if(isoct~=0)
|
||||
numstr=regexp(currstr,'^\s*-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?','end');
|
||||
[num] = sscanf(currstr, '%f', 1);
|
||||
delta=numstr+1;
|
||||
else
|
||||
[num, one, err, delta] = sscanf(currstr, '%f', 1);
|
||||
if ~isempty(err)
|
||||
error_pos('Error reading number at position %d',inStr);
|
||||
end
|
||||
end
|
||||
pos = pos + delta-1;
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function val = parse_value(inStr, esc, varargin)
|
||||
import jsonlab.*
|
||||
global pos
|
||||
len=length(inStr);
|
||||
if(isfield(varargin{1},'progressbar_'))
|
||||
waitbar(pos/len,varargin{1}.progressbar_,'loading ...');
|
||||
end
|
||||
|
||||
switch(inStr(pos))
|
||||
case '"'
|
||||
val = parseStr(inStr, esc, varargin{:});
|
||||
return;
|
||||
case '['
|
||||
val = parse_array(inStr, esc, varargin{:});
|
||||
return;
|
||||
case '{'
|
||||
val = parse_object(inStr, esc, varargin{:});
|
||||
return;
|
||||
case {'-','0','1','2','3','4','5','6','7','8','9'}
|
||||
val = parse_number(inStr, varargin{:});
|
||||
return;
|
||||
case 't'
|
||||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'true')
|
||||
val = true;
|
||||
pos = pos + 4;
|
||||
return;
|
||||
end
|
||||
case 'f'
|
||||
if pos+4 <= len && strcmpi(inStr(pos:pos+4), 'false')
|
||||
val = false;
|
||||
pos = pos + 5;
|
||||
return;
|
||||
end
|
||||
case 'n'
|
||||
if pos+3 <= len && strcmpi(inStr(pos:pos+3), 'null')
|
||||
val = [];
|
||||
pos = pos + 4;
|
||||
return;
|
||||
end
|
||||
end
|
||||
error_pos('Value expected at position %d',inStr);
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function error_pos(msg, inStr)
|
||||
import jsonlab.*
|
||||
global pos len
|
||||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
|
||||
if poShow(3) == poShow(2)
|
||||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after
|
||||
end
|
||||
msg = [sprintf(msg, pos) ': ' ...
|
||||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
|
||||
error( ['JSONparser:invalidFormat: ' msg] );
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function str = valid_field(str)
|
||||
import jsonlab.*
|
||||
global isoct
|
||||
% From MATLAB doc: field names must begin with a letter, which may be
|
||||
% followed by any combination of letters, digits, and underscores.
|
||||
% Invalid characters will be converted to underscores, and the prefix
|
||||
% "x0x[Hex code]_" will be added if the first character is not a letter.
|
||||
pos=regexp(str,'^[^A-Za-z]','once');
|
||||
if(~isempty(pos))
|
||||
if(~isoct && str(1)+0 > 255)
|
||||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
|
||||
else
|
||||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
|
||||
end
|
||||
end
|
||||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' )))
|
||||
return;
|
||||
end
|
||||
if(~isoct)
|
||||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
|
||||
else
|
||||
pos=regexp(str,'[^0-9A-Za-z_]');
|
||||
if(isempty(pos))
|
||||
return;
|
||||
end
|
||||
str0=str;
|
||||
pos0=[0 pos(:)' length(str)];
|
||||
str='';
|
||||
for i=1:length(pos)
|
||||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
|
||||
end
|
||||
if(pos(end)~=length(str))
|
||||
str=[str str0(pos0(end-1)+1:pos0(end))];
|
||||
end
|
||||
end
|
||||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_';
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function endpos = matching_quote(str,pos)
|
||||
import jsonlab.*
|
||||
len=length(str);
|
||||
while(pos<len)
|
||||
if(str(pos)=='"')
|
||||
if(~(pos>1 && str(pos-1)=='\'))
|
||||
endpos=pos;
|
||||
return;
|
||||
end
|
||||
end
|
||||
pos=pos+1;
|
||||
end
|
||||
error('unmatched quotation mark');
|
||||
%%-------------------------------------------------------------------------
|
||||
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos)
|
||||
import jsonlab.*
|
||||
global arraytoken
|
||||
level=1;
|
||||
maxlevel=level;
|
||||
endpos=0;
|
||||
bpos=arraytoken(arraytoken>=pos);
|
||||
tokens=str(bpos);
|
||||
len=length(tokens);
|
||||
pos=1;
|
||||
e1l=[];
|
||||
e1r=[];
|
||||
while(pos<=len)
|
||||
c=tokens(pos);
|
||||
if(c==']')
|
||||
level=level-1;
|
||||
if(isempty(e1r))
|
||||
e1r=bpos(pos);
|
||||
end
|
||||
if(level==0)
|
||||
endpos=bpos(pos);
|
||||
return
|
||||
end
|
||||
elseif(c=='[')
|
||||
if(isempty(e1l))
|
||||
e1l=bpos(pos);
|
||||
end
|
||||
level=level+1;
|
||||
maxlevel=max(maxlevel,level);
|
||||
elseif(c=='"')
|
||||
pos=matching_quote(tokens,pos+1);
|
||||
end
|
||||
pos=pos+1;
|
||||
end
|
||||
if(endpos==0)
|
||||
error('unmatched "]"');
|
||||
end
|
||||
|
||||
function newstr=unescapejsonstring(str)
|
||||
import jsonlab.*
|
||||
newstr=str;
|
||||
if(~ischar(str))
|
||||
return;
|
||||
end
|
||||
escapechars={'\\','\"','\/','\a','\b','\f','\n','\r','\t','\v'};
|
||||
for i=1:length(escapechars);
|
||||
newstr=regexprep(newstr,regexprep(escapechars{i},'\\','\\\\'), escapechars{i});
|
||||
end
|
||||
newstr=regexprep(newstr,'\\u([0-9A-Fa-f]{4})', '${char(base2dec($1,16))}');
|
||||
|
|
@ -0,0 +1,465 @@
|
|||
function data = loadubjson(fname,varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% data=loadubjson(fname,opt)
|
||||
% or
|
||||
% data=loadubjson(fname,'param1',value1,'param2',value2,...)
|
||||
%
|
||||
% parse a JSON (JavaScript Object Notation) file or string
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
% created on 2013/08/01
|
||||
%
|
||||
% $Id$
|
||||
%
|
||||
% input:
|
||||
% fname: input file name, if fname contains "{}" or "[]", fname
|
||||
% will be interpreted as a UBJSON string
|
||||
% opt: a struct to store parsing options, opt can be replaced by
|
||||
% a list of ('param',value) pairs - the param string is equivallent
|
||||
% to a field in opt. opt can have the following
|
||||
% fields (first in [.|.] is the default)
|
||||
%
|
||||
% opt.SimplifyCell [0|1]: if set to 1, loadubjson will call cell2mat
|
||||
% for each element of the JSON data, and group
|
||||
% arrays based on the cell2mat rules.
|
||||
% opt.IntEndian [B|L]: specify the endianness of the integer fields
|
||||
% in the UBJSON input data. B - Big-Endian format for
|
||||
% integers (as required in the UBJSON specification);
|
||||
% L - input integer fields are in Little-Endian order.
|
||||
% opt.NameIsString [0|1]: for UBJSON Specification Draft 8 or
|
||||
% earlier versions (JSONLab 1.0 final or earlier),
|
||||
% the "name" tag is treated as a string. To load
|
||||
% these UBJSON data, you need to manually set this
|
||||
% flag to 1.
|
||||
%
|
||||
% output:
|
||||
% dat: a cell array, where {...} blocks are converted into cell arrays,
|
||||
% and [...] are converted to arrays
|
||||
%
|
||||
% examples:
|
||||
% obj=struct('string','value','array',[1 2 3]);
|
||||
% ubjdata=saveubjson('obj',obj);
|
||||
% dat=loadubjson(ubjdata)
|
||||
% dat=loadubjson(['examples' filesep 'example1.ubj'])
|
||||
% dat=loadubjson(['examples' filesep 'example1.ubj'],'SimplifyCell',1)
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
global pos inStr len esc index_esc len_esc isoct arraytoken fileendian systemendian
|
||||
|
||||
if(regexp(fname,'[\{\}\]\[]','once'))
|
||||
string=fname;
|
||||
elseif(exist(fname,'file'))
|
||||
fid = fopen(fname,'rb');
|
||||
string = fread(fid,inf,'uint8=>char')';
|
||||
fclose(fid);
|
||||
else
|
||||
error('input file does not exist');
|
||||
end
|
||||
|
||||
pos = 1; len = length(string); inStr = string;
|
||||
isoct=exist('OCTAVE_VERSION','builtin');
|
||||
arraytoken=find(inStr=='[' | inStr==']' | inStr=='"');
|
||||
jstr=regexprep(inStr,'\\\\',' ');
|
||||
escquote=regexp(jstr,'\\"');
|
||||
arraytoken=sort([arraytoken escquote]);
|
||||
|
||||
% String delimiters and escape chars identified to improve speed:
|
||||
esc = find(inStr=='"' | inStr=='\' ); % comparable to: regexp(inStr, '["\\]');
|
||||
index_esc = 1; len_esc = length(esc);
|
||||
|
||||
opt=varargin2struct(varargin{:});
|
||||
fileendian=upper(jsonopt('IntEndian','B',opt));
|
||||
[os,maxelem,systemendian]=computer;
|
||||
|
||||
jsoncount=1;
|
||||
while pos <= len
|
||||
switch(next_char)
|
||||
case '{'
|
||||
data{jsoncount} = parse_object(opt);
|
||||
case '['
|
||||
data{jsoncount} = parse_array(opt);
|
||||
otherwise
|
||||
error_pos('Outer level structure must be an object or an array');
|
||||
end
|
||||
jsoncount=jsoncount+1;
|
||||
end % while
|
||||
|
||||
jsoncount=length(data);
|
||||
if(jsoncount==1 && iscell(data))
|
||||
data=data{1};
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function object = parse_object(varargin)
|
||||
import jsonlab.*
|
||||
parse_char('{');
|
||||
object = [];
|
||||
type='';
|
||||
count=-1;
|
||||
if(next_char == '$')
|
||||
type=inStr(pos+1); % TODO
|
||||
pos=pos+2;
|
||||
end
|
||||
if(next_char == '#')
|
||||
pos=pos+1;
|
||||
count=double(parse_number());
|
||||
end
|
||||
if next_char ~= '}'
|
||||
num=0;
|
||||
while 1
|
||||
if(jsonopt('NameIsString',0,varargin{:}))
|
||||
str = parseStr(varargin{:});
|
||||
else
|
||||
str = parse_name(varargin{:});
|
||||
end
|
||||
if isempty(str)
|
||||
error_pos('Name of value at position %d cannot be empty');
|
||||
end
|
||||
%parse_char(':');
|
||||
val = parse_value(varargin{:});
|
||||
num=num+1;
|
||||
object.(valid_field(str))=val;
|
||||
if next_char == '}' || (count>=0 && num>=count)
|
||||
break;
|
||||
end
|
||||
%parse_char(',');
|
||||
end
|
||||
end
|
||||
if(count==-1)
|
||||
parse_char('}');
|
||||
end
|
||||
if(isstruct(object))
|
||||
object=struct2jdata(object,struct('Base64',0));
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function [cid,len]=elem_info(type)
|
||||
import jsonlab.*
|
||||
id=strfind('iUIlLdD',type);
|
||||
dataclass={'int8','uint8','int16','int32','int64','single','double'};
|
||||
bytelen=[1,1,2,4,8,4,8];
|
||||
if(id>0)
|
||||
cid=dataclass{id};
|
||||
len=bytelen(id);
|
||||
else
|
||||
error_pos('unsupported type at position %d');
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
|
||||
function [data, adv]=parse_block(type,count,varargin)
|
||||
import jsonlab.*
|
||||
global pos inStr isoct fileendian systemendian
|
||||
[cid,len]=elem_info(type);
|
||||
datastr=inStr(pos:pos+len*count-1);
|
||||
newdata=uint8(datastr);
|
||||
id=strfind('iUIlLdD',type);
|
||||
if(fileendian~=systemendian)
|
||||
newdata=swapbytes(typecast(newdata,cid));
|
||||
end
|
||||
data=typecast(newdata,cid);
|
||||
adv=double(len*count);
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
|
||||
function object = parse_array(varargin) % JSON array is written in row-major order
|
||||
import jsonlab.*
|
||||
global pos inStr
|
||||
parse_char('[');
|
||||
object = cell(0, 1);
|
||||
dim=[];
|
||||
type='';
|
||||
count=-1;
|
||||
if(next_char == '$')
|
||||
type=inStr(pos+1);
|
||||
pos=pos+2;
|
||||
end
|
||||
if(next_char == '#')
|
||||
pos=pos+1;
|
||||
if(next_char=='[')
|
||||
dim=parse_array(varargin{:});
|
||||
count=prod(double(dim));
|
||||
else
|
||||
count=double(parse_number());
|
||||
end
|
||||
end
|
||||
if(~isempty(type))
|
||||
if(count>=0)
|
||||
[object, adv]=parse_block(type,count,varargin{:});
|
||||
if(~isempty(dim))
|
||||
object=reshape(object,dim);
|
||||
end
|
||||
pos=pos+adv;
|
||||
return;
|
||||
else
|
||||
endpos=matching_bracket(inStr,pos);
|
||||
[cid,len]=elem_info(type);
|
||||
count=(endpos-pos)/len;
|
||||
[object, adv]=parse_block(type,count,varargin{:});
|
||||
pos=pos+adv;
|
||||
parse_char(']');
|
||||
return;
|
||||
end
|
||||
end
|
||||
if next_char ~= ']'
|
||||
while 1
|
||||
val = parse_value(varargin{:});
|
||||
object{end+1} = val;
|
||||
if next_char == ']'
|
||||
break;
|
||||
end
|
||||
%parse_char(',');
|
||||
end
|
||||
end
|
||||
if(jsonopt('SimplifyCell',0,varargin{:})==1)
|
||||
try
|
||||
oldobj=object;
|
||||
object=cell2mat(object')';
|
||||
if(iscell(oldobj) && isstruct(object) && numel(object)>1 && jsonopt('SimplifyCellArray',1,varargin{:})==0)
|
||||
object=oldobj;
|
||||
elseif(size(object,1)>1 && ismatrix(object))
|
||||
object=object';
|
||||
end
|
||||
catch
|
||||
end
|
||||
end
|
||||
if(count==-1)
|
||||
parse_char(']');
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function parse_char(c)
|
||||
import jsonlab.*
|
||||
global pos inStr len
|
||||
skip_whitespace;
|
||||
if pos > len || inStr(pos) ~= c
|
||||
error_pos(sprintf('Expected %c at position %%d', c));
|
||||
else
|
||||
pos = pos + 1;
|
||||
skip_whitespace;
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function c = next_char
|
||||
import jsonlab.*
|
||||
global pos inStr len
|
||||
skip_whitespace;
|
||||
if pos > len
|
||||
c = [];
|
||||
else
|
||||
c = inStr(pos);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function skip_whitespace
|
||||
import jsonlab.*
|
||||
global pos inStr len
|
||||
while pos <= len && isspace(inStr(pos))
|
||||
pos = pos + 1;
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function str = parse_name(varargin)
|
||||
import jsonlab.*
|
||||
global pos inStr
|
||||
bytelen=double(parse_number());
|
||||
if(length(inStr)>=pos+bytelen-1)
|
||||
str=inStr(pos:pos+bytelen-1);
|
||||
pos=pos+bytelen;
|
||||
else
|
||||
error_pos('End of file while expecting end of name');
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function str = parseStr(varargin)
|
||||
import jsonlab.*
|
||||
global pos inStr
|
||||
% len, ns = length(inStr), keyboard
|
||||
type=inStr(pos);
|
||||
if type ~= 'S' && type ~= 'C' && type ~= 'H'
|
||||
error_pos('String starting with S expected at position %d');
|
||||
else
|
||||
pos = pos + 1;
|
||||
end
|
||||
if(type == 'C')
|
||||
str=inStr(pos);
|
||||
pos=pos+1;
|
||||
return;
|
||||
end
|
||||
bytelen=double(parse_number());
|
||||
if(length(inStr)>=pos+bytelen-1)
|
||||
str=inStr(pos:pos+bytelen-1);
|
||||
pos=pos+bytelen;
|
||||
else
|
||||
error_pos('End of file while expecting end of inStr');
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function num = parse_number(varargin)
|
||||
import jsonlab.*
|
||||
global pos inStr isoct fileendian systemendian
|
||||
id=strfind('iUIlLdD',inStr(pos));
|
||||
if(isempty(id))
|
||||
error_pos('expecting a number at position %d');
|
||||
end
|
||||
type={'int8','uint8','int16','int32','int64','single','double'};
|
||||
bytelen=[1,1,2,4,8,4,8];
|
||||
datastr=inStr(pos+1:pos+bytelen(id));
|
||||
newdata=uint8(datastr);
|
||||
if(fileendian~=systemendian)
|
||||
newdata=swapbytes(typecast(newdata,type{id}));
|
||||
end
|
||||
num=typecast(newdata,type{id});
|
||||
pos = pos + bytelen(id)+1;
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function val = parse_value(varargin)
|
||||
import jsonlab.*
|
||||
global pos inStr
|
||||
|
||||
switch(inStr(pos))
|
||||
case {'S','C','H'}
|
||||
val = parseStr(varargin{:});
|
||||
return;
|
||||
case '['
|
||||
val = parse_array(varargin{:});
|
||||
return;
|
||||
case '{'
|
||||
val = parse_object(varargin{:});
|
||||
return;
|
||||
case {'i','U','I','l','L','d','D'}
|
||||
val = parse_number(varargin{:});
|
||||
return;
|
||||
case 'T'
|
||||
val = true;
|
||||
pos = pos + 1;
|
||||
return;
|
||||
case 'F'
|
||||
val = false;
|
||||
pos = pos + 1;
|
||||
return;
|
||||
case {'Z','N'}
|
||||
val = [];
|
||||
pos = pos + 1;
|
||||
return;
|
||||
end
|
||||
error_pos('Value expected at position %d');
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function error_pos(msg)
|
||||
import jsonlab.*
|
||||
global pos inStr len
|
||||
poShow = max(min([pos-15 pos-1 pos pos+20],len),1);
|
||||
if poShow(3) == poShow(2)
|
||||
poShow(3:4) = poShow(2)+[0 -1]; % display nothing after
|
||||
end
|
||||
msg = [sprintf(msg, pos) ': ' ...
|
||||
inStr(poShow(1):poShow(2)) '<error>' inStr(poShow(3):poShow(4)) ];
|
||||
error( ['JSONparser:invalidFormat: ' msg] );
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
|
||||
function str = valid_field(str)
|
||||
import jsonlab.*
|
||||
global isoct
|
||||
% From MATLAB doc: field names must begin with a letter, which may be
|
||||
% followed by any combination of letters, digits, and underscores.
|
||||
% Invalid characters will be converted to underscores, and the prefix
|
||||
% "x0x[Hex code]_" will be added if the first character is not a letter.
|
||||
pos=regexp(str,'^[^A-Za-z]','once');
|
||||
if(~isempty(pos))
|
||||
if(~isoct)
|
||||
str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
|
||||
else
|
||||
str=sprintf('x0x%X_%s',char(str(1)),str(2:end));
|
||||
end
|
||||
end
|
||||
if(isempty(regexp(str,'[^0-9A-Za-z_]', 'once' )))
|
||||
return;
|
||||
end
|
||||
if(~isoct)
|
||||
str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
|
||||
else
|
||||
pos=regexp(str,'[^0-9A-Za-z_]');
|
||||
if(isempty(pos))
|
||||
return;
|
||||
end
|
||||
str0=str;
|
||||
pos0=[0 pos(:)' length(str)];
|
||||
str='';
|
||||
for i=1:length(pos)
|
||||
str=[str str0(pos0(i)+1:pos(i)-1) sprintf('_0x%X_',str0(pos(i)))];
|
||||
end
|
||||
if(pos(end)~=length(str))
|
||||
str=[str str0(pos0(end-1)+1:pos0(end))];
|
||||
end
|
||||
end
|
||||
%str(~isletter(str) & ~('0' <= str & str <= '9')) = '_';
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function endpos = matching_quote(str,pos)
|
||||
import jsonlab.*
|
||||
len=length(str);
|
||||
while(pos<len)
|
||||
if(str(pos)=='"')
|
||||
if(~(pos>1 && str(pos-1)=='\'))
|
||||
endpos=pos;
|
||||
return;
|
||||
end
|
||||
end
|
||||
pos=pos+1;
|
||||
end
|
||||
error('unmatched quotation mark');
|
||||
%%-------------------------------------------------------------------------
|
||||
function [endpos, e1l, e1r, maxlevel] = matching_bracket(str,pos)
|
||||
import jsonlab.*
|
||||
global arraytoken
|
||||
level=1;
|
||||
maxlevel=level;
|
||||
endpos=0;
|
||||
bpos=arraytoken(arraytoken>=pos);
|
||||
tokens=str(bpos);
|
||||
len=length(tokens);
|
||||
pos=1;
|
||||
e1l=[];
|
||||
e1r=[];
|
||||
while(pos<=len)
|
||||
c=tokens(pos);
|
||||
if(c==']')
|
||||
level=level-1;
|
||||
if(isempty(e1r))
|
||||
e1r=bpos(pos);
|
||||
end
|
||||
if(level==0)
|
||||
endpos=bpos(pos);
|
||||
return
|
||||
end
|
||||
end
|
||||
if(c=='[')
|
||||
if(isempty(e1l))
|
||||
e1l=bpos(pos);
|
||||
end
|
||||
level=level+1;
|
||||
maxlevel=max(maxlevel,level);
|
||||
end
|
||||
if(c=='"')
|
||||
pos=matching_quote(tokens,pos+1);
|
||||
end
|
||||
pos=pos+1;
|
||||
end
|
||||
if(endpos==0)
|
||||
error('unmatched "]"');
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
function s=mergestruct(s1,s2)
|
||||
import jsonlab.*
|
||||
%
|
||||
% s=mergestruct(s1,s2)
|
||||
%
|
||||
% merge two struct objects into one
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
% date: 2012/12/22
|
||||
%
|
||||
% input:
|
||||
% s1,s2: a struct object, s1 and s2 can not be arrays
|
||||
%
|
||||
% output:
|
||||
% s: the merged struct object. fields in s1 and s2 will be combined in s.
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
if(~isstruct(s1) || ~isstruct(s2))
|
||||
error('input parameters contain non-struct');
|
||||
end
|
||||
if(length(s1)>1 || length(s2)>1)
|
||||
error('can not merge struct arrays');
|
||||
end
|
||||
fn=fieldnames(s2);
|
||||
s=s1;
|
||||
for i=1:length(fn)
|
||||
s=setfield(s,fn{i},getfield(s2,fn{i}));
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "jsonlab",
|
||||
"version": "1.9",
|
||||
"description": "An open-source MATLAB/Octave JSON encoder and decoder",
|
||||
"directories": {
|
||||
"example": "examples"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/fangq/jsonlab.git"
|
||||
},
|
||||
"author": "Qianqian Fang <q.fang at neu.edu>",
|
||||
"license": "BSD",
|
||||
"bugs": {
|
||||
"url": "https://github.com/fangq/jsonlab/issues"
|
||||
},
|
||||
"homepage": "https://iso2mesh.sf.net/jsonlab/"
|
||||
}
|
||||
|
|
@ -0,0 +1,686 @@
|
|||
function json=savejson(rootname,obj,varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% json=savejson(rootname,obj,filename)
|
||||
% or
|
||||
% json=savejson(rootname,obj,opt)
|
||||
% json=savejson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
%
|
||||
% convert a MATLAB object (cell, struct or array) into a JSON (JavaScript
|
||||
% Object Notation) string
|
||||
%
|
||||
% author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
% created on 2011/09/09
|
||||
%
|
||||
% $Id$
|
||||
%
|
||||
% input:
|
||||
% rootname: the name of the root-object, when set to '', the root name
|
||||
% is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
% the MATLAB variable name will be used as the root name.
|
||||
% obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
% class instance).
|
||||
% filename: a string for the file name to save the output JSON data.
|
||||
% opt: a struct for additional options, ignore to use default values.
|
||||
% opt can have the following fields (first in [.|.] is the default)
|
||||
%
|
||||
% opt.FileName [''|string]: a file name to save the output JSON data
|
||||
% opt.FloatFormat ['%.10g'|string]: format to show each numeric element
|
||||
% of a 1D/2D array;
|
||||
% opt.ArrayIndent [1|0]: if 1, output explicit data array with
|
||||
% precedent indentation; if 0, no indentation
|
||||
% opt.ArrayToStruct[0|1]: when set to 0, savejson outputs 1D/2D
|
||||
% array in JSON array format; if sets to 1, an
|
||||
% array will be shown as a struct with fields
|
||||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
% sparse arrays, the non-zero elements will be
|
||||
% saved to _ArrayData_ field in triplet-format i.e.
|
||||
% (ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
% with a value of 1; for a complex array, the
|
||||
% _ArrayData_ array will include two columns
|
||||
% (4 for sparse) to record the real and imaginary
|
||||
% parts, and also "_ArrayIsComplex_":1 is added.
|
||||
% opt.ParseLogical [0|1]: if this is set to 1, logical array elem
|
||||
% will use true/false rather than 1/0.
|
||||
% opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
% numerical element will be shown without a square
|
||||
% bracket, unless it is the root object; if 0, square
|
||||
% brackets are forced for any numerical arrays.
|
||||
% opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
% even it has only one element; if 0, brackets
|
||||
% are ignored when a cell has only 1 element.
|
||||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, savejson
|
||||
% will use the name of the passed obj variable as the
|
||||
% root object name; if obj is an expression and
|
||||
% does not have a name, 'root' will be used; if this
|
||||
% is set to 0 and rootname is empty, the root level
|
||||
% will be merged down to the lower level.
|
||||
% opt.Inf ['"$1_Inf_"'|string]: a customized regular expression pattern
|
||||
% to represent +/-Inf. The matched pattern is '([-+]*)Inf'
|
||||
% and $1 represents the sign. For those who want to use
|
||||
% 1e999 to represent Inf, they can set opt.Inf to '$11e999'
|
||||
% opt.NaN ['"_NaN_"'|string]: a customized regular expression pattern
|
||||
% to represent NaN
|
||||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
% for example, if opt.JSONP='foo', the JSON data is
|
||||
% wrapped inside a function call as 'foo(...);'
|
||||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
% back to the string form
|
||||
% opt.SaveBinary [0|1]: 1 - save the JSON file in binary mode; 0 - text mode.
|
||||
% opt.Compact [0|1]: 1- out compact JSON format (remove all newlines and tabs)
|
||||
% opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
% method; currently only supports 'gzip' or 'zlib'. The
|
||||
% data compression only applicable to numerical arrays
|
||||
% in 3D or higher dimensions, or when ArrayToStruct
|
||||
% is 1 for 1D or 2D arrays. If one wants to
|
||||
% compress a long string, one must convert
|
||||
% it to uint8 or int8 array first. The compressed
|
||||
% array uses three extra fields
|
||||
% "_ArrayCompressionMethod_": the opt.Compression value.
|
||||
% "_ArrayCompressionSize_": a 1D interger array to
|
||||
% store the pre-compressed (but post-processed)
|
||||
% array dimensions, and
|
||||
% "_ArrayCompressedData_": the "base64" encoded
|
||||
% compressed binary array data.
|
||||
% opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
% element count is larger than this number.
|
||||
% opt can be replaced by a list of ('param',value) pairs. The param
|
||||
% string is equivallent to a field in opt and is case sensitive.
|
||||
% output:
|
||||
% json: a string in the JSON format (see http://json.org)
|
||||
%
|
||||
% examples:
|
||||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
% 'SpecialData',[nan, inf, -inf]);
|
||||
% savejson('jmesh',jsonmesh)
|
||||
% savejson('',jsonmesh,'ArrayIndent',0,'FloatFormat','\t%.5g')
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
if(nargin==1)
|
||||
varname=inputname(1);
|
||||
obj=rootname;
|
||||
if(isempty(varname))
|
||||
varname='root';
|
||||
end
|
||||
rootname=varname;
|
||||
else
|
||||
varname=inputname(2);
|
||||
end
|
||||
if(length(varargin)==1 && ischar(varargin{1}))
|
||||
opt=struct('filename',varargin{1});
|
||||
else
|
||||
opt=varargin2struct(varargin{:});
|
||||
end
|
||||
opt.IsOctave=exist('OCTAVE_VERSION','builtin');
|
||||
|
||||
dozip=jsonopt('Compression','',opt);
|
||||
if(~isempty(dozip))
|
||||
if(~(strcmpi(dozip,'gzip') || strcmpi(dozip,'zlib')))
|
||||
error('compression method "%s" is not supported',dozip);
|
||||
end
|
||||
if(exist('zmat')~=3)
|
||||
try
|
||||
error(javachk('jvm'));
|
||||
try
|
||||
base64decode('test');
|
||||
catch
|
||||
matlab.net.base64decode('test');
|
||||
end
|
||||
catch
|
||||
error('java-based compression is not supported');
|
||||
end
|
||||
end
|
||||
opt.Compression=dozip;
|
||||
end
|
||||
|
||||
if(isfield(opt,'norowbracket'))
|
||||
warning('Option ''NoRowBracket'' is depreciated, please use ''SingletArray'' and set its value to not(NoRowBracket)');
|
||||
if(~isfield(opt,'singletarray'))
|
||||
opt.singletarray=not(opt.norowbracket);
|
||||
end
|
||||
end
|
||||
rootisarray=0;
|
||||
rootlevel=1;
|
||||
forceroot=jsonopt('ForceRootName',0,opt);
|
||||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || ...
|
||||
iscell(obj) || isobject(obj)) && isempty(rootname) && forceroot==0)
|
||||
rootisarray=1;
|
||||
rootlevel=0;
|
||||
else
|
||||
if(isempty(rootname))
|
||||
rootname=varname;
|
||||
end
|
||||
end
|
||||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot)
|
||||
rootname='root';
|
||||
end
|
||||
|
||||
whitespaces=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
||||
if(jsonopt('Compact',0,opt)==1)
|
||||
whitespaces=struct('tab','','newline','','sep',',');
|
||||
end
|
||||
if(~isfield(opt,'whitespaces_'))
|
||||
opt.whitespaces_=whitespaces;
|
||||
end
|
||||
|
||||
nl=whitespaces.newline;
|
||||
|
||||
json=obj2json(rootname,obj,rootlevel,opt);
|
||||
if(rootisarray)
|
||||
json=sprintf('%s%s',json,nl);
|
||||
else
|
||||
json=sprintf('{%s%s%s}\n',nl,json,nl);
|
||||
end
|
||||
|
||||
jsonp=jsonopt('JSONP','',opt);
|
||||
if(~isempty(jsonp))
|
||||
json=sprintf('%s(%s);%s',jsonp,json,nl);
|
||||
end
|
||||
|
||||
% save to a file if FileName is set, suggested by Patrick Rapin
|
||||
filename=jsonopt('FileName','',opt);
|
||||
if(~isempty(filename))
|
||||
if(jsonopt('SaveBinary',0,opt)==1)
|
||||
fid = fopen(filename, 'wb');
|
||||
fwrite(fid,json);
|
||||
else
|
||||
fid = fopen(filename, 'wt');
|
||||
fwrite(fid,json,'char');
|
||||
end
|
||||
fclose(fid);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=obj2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
|
||||
if(iscell(item) || isa(item,'string'))
|
||||
txt=cell2json(name,item,level,varargin{:});
|
||||
elseif(isstruct(item))
|
||||
txt=struct2json(name,item,level,varargin{:});
|
||||
elseif(ischar(item))
|
||||
txt=str2json(name,item,level,varargin{:});
|
||||
elseif(isobject(item))
|
||||
if(~exist('OCTAVE_VERSION','builtin') && exist('istable','builtin') && istable(item))
|
||||
txt=matlabtable2json(name,item,level,varargin{:});
|
||||
else
|
||||
txt=matlabobject2json(name,item,level,varargin{:});
|
||||
end
|
||||
elseif(isa(item,'function_handle'))
|
||||
txt=struct2json(name,functions(item),level,varargin{:});
|
||||
else
|
||||
txt=mat2json(name,item,level,varargin{:});
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=cell2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt={};
|
||||
if(~iscell(item) && ~isa(item,'string'))
|
||||
error('input is not a cell or string array');
|
||||
end
|
||||
|
||||
dim=size(item);
|
||||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
||||
item=reshape(item,dim(1),numel(item)/dim(1));
|
||||
dim=size(item);
|
||||
end
|
||||
len=numel(item);
|
||||
ws=jsonopt('whitespaces_',struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n')),varargin{:});
|
||||
padding0=repmat(ws.tab,1,level);
|
||||
padding2=repmat(ws.tab,1,level+1);
|
||||
nl=ws.newline;
|
||||
bracketlevel=~jsonopt('singletcell',1,varargin{:});
|
||||
if(len>bracketlevel)
|
||||
if(~isempty(name))
|
||||
txt={padding0, '"', checkname(name,varargin{:}),'": [', nl}; name='';
|
||||
else
|
||||
txt={padding0, '[', nl};
|
||||
end
|
||||
elseif(len==0)
|
||||
if(~isempty(name))
|
||||
txt={padding0, '"' checkname(name,varargin{:}) '": []'}; name='';
|
||||
else
|
||||
txt={padding0, '[]'};
|
||||
end
|
||||
end
|
||||
for i=1:dim(1)
|
||||
if(dim(1)>1)
|
||||
txt(end+1:end+3)={padding2,'[',nl};
|
||||
end
|
||||
for j=1:dim(2)
|
||||
txt{end+1}=obj2json(name,item{i,j},level+(dim(1)>1)+(len>bracketlevel),varargin{:});
|
||||
if(j<dim(2))
|
||||
txt(end+1:end+2)={',' nl};
|
||||
end
|
||||
end
|
||||
if(dim(1)>1)
|
||||
txt(end+1:end+3)={nl,padding2,']'};
|
||||
end
|
||||
if(i<dim(1))
|
||||
txt(end+1:end+2)={',' nl};
|
||||
end
|
||||
%if(j==dim(2)) txt=sprintf('%s%s',txt,sprintf(',%s',nl)); end
|
||||
end
|
||||
if(len>bracketlevel)
|
||||
txt(end+1:end+3)={nl,padding0,']'};
|
||||
end
|
||||
txt = sprintf('%s',txt{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=struct2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt={};
|
||||
if(~isstruct(item))
|
||||
error('input is not a struct');
|
||||
end
|
||||
dim=size(item);
|
||||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
||||
item=reshape(item,dim(1),numel(item)/dim(1));
|
||||
dim=size(item);
|
||||
end
|
||||
len=numel(item);
|
||||
forcearray= (len>1 || (jsonopt('SingletArray',0,varargin{:})==1 && level>0));
|
||||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'));
|
||||
ws=jsonopt('whitespaces_',ws,varargin{:});
|
||||
padding0=repmat(ws.tab,1,level);
|
||||
padding2=repmat(ws.tab,1,level+1);
|
||||
padding1=repmat(ws.tab,1,level+(dim(1)>1)+forcearray);
|
||||
nl=ws.newline;
|
||||
|
||||
if(isempty(item))
|
||||
if(~isempty(name))
|
||||
txt={padding0, '"', checkname(name,varargin{:}),'": []'};
|
||||
else
|
||||
txt={padding0, '[]'};
|
||||
end
|
||||
txt = sprintf('%s',txt{:});
|
||||
return;
|
||||
end
|
||||
if(~isempty(name))
|
||||
if(forcearray)
|
||||
txt={padding0, '"', checkname(name,varargin{:}),'": [', nl};
|
||||
end
|
||||
else
|
||||
if(forcearray)
|
||||
txt={padding0, '[', nl};
|
||||
end
|
||||
end
|
||||
for j=1:dim(2)
|
||||
if(dim(1)>1)
|
||||
txt(end+1:end+3)={padding2,'[',nl};
|
||||
end
|
||||
for i=1:dim(1)
|
||||
names = fieldnames(item(i,j));
|
||||
if(~isempty(name) && len==1 && ~forcearray)
|
||||
txt(end+1:end+5)={padding1, '"', checkname(name,varargin{:}),'": {', nl};
|
||||
else
|
||||
txt(end+1:end+3)={padding1, '{', nl};
|
||||
end
|
||||
if(~isempty(names))
|
||||
for e=1:length(names)
|
||||
txt{end+1}=obj2json(names{e},item(i,j).(names{e}),...
|
||||
level+(dim(1)>1)+1+forcearray,varargin{:});
|
||||
if(e<length(names))
|
||||
txt{end+1}=',';
|
||||
end
|
||||
txt{end+1}=nl;
|
||||
end
|
||||
end
|
||||
txt(end+1:end+2)={padding1,'}'};
|
||||
if(i<dim(1))
|
||||
txt(end+1:end+2)={',' nl};
|
||||
end
|
||||
end
|
||||
if(dim(1)>1)
|
||||
txt(end+1:end+3)={nl,padding2,']'};
|
||||
end
|
||||
if(j<dim(2))
|
||||
txt(end+1:end+2)={',' nl};
|
||||
end
|
||||
end
|
||||
if(forcearray)
|
||||
txt(end+1:end+3)={nl,padding0,']'};
|
||||
end
|
||||
txt = sprintf('%s',txt{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=str2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt={};
|
||||
if(~ischar(item))
|
||||
error('input is not a string');
|
||||
end
|
||||
item=reshape(item, max(size(item),[1 0]));
|
||||
len=size(item,1);
|
||||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
||||
ws=jsonopt('whitespaces_',ws,varargin{:});
|
||||
padding1=repmat(ws.tab,1,level);
|
||||
padding0=repmat(ws.tab,1,level+1);
|
||||
nl=ws.newline;
|
||||
sep=ws.sep;
|
||||
|
||||
if(~isempty(name))
|
||||
if(len>1)
|
||||
txt={padding1, '"', checkname(name,varargin{:}),'": [', nl};
|
||||
end
|
||||
else
|
||||
if(len>1)
|
||||
txt={padding1, '[', nl};
|
||||
end
|
||||
end
|
||||
for e=1:len
|
||||
val=escapejsonstring(item(e,:));
|
||||
if(len==1)
|
||||
obj=['"' checkname(name,varargin{:}) '": ' '"',val,'"'];
|
||||
if(isempty(name))
|
||||
obj=['"',val,'"'];
|
||||
end
|
||||
txt(end+1:end+2)={padding1, obj};
|
||||
else
|
||||
txt(end+1:end+4)={padding0,'"',val,'"'};
|
||||
end
|
||||
if(e==len)
|
||||
sep='';
|
||||
end
|
||||
txt{end+1}=sep;
|
||||
end
|
||||
if(len>1)
|
||||
txt(end+1:end+3)={nl,padding1,']'};
|
||||
end
|
||||
txt = sprintf('%s',txt{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=mat2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
if(~isnumeric(item) && ~islogical(item))
|
||||
error('input is not an array');
|
||||
end
|
||||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
||||
ws=jsonopt('whitespaces_',ws,varargin{:});
|
||||
padding1=repmat(ws.tab,1,level);
|
||||
padding0=repmat(ws.tab,1,level+1);
|
||||
nl=ws.newline;
|
||||
sep=ws.sep;
|
||||
|
||||
dozip=jsonopt('Compression','',varargin{:});
|
||||
zipsize=jsonopt('CompressArraySize',100,varargin{:});
|
||||
|
||||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ...
|
||||
(isempty(item) && any(size(item))) ||jsonopt('ArrayToStruct',0,varargin{:}) || (~isempty(dozip) && numel(item)>zipsize))
|
||||
if(isempty(name))
|
||||
txt=sprintf('%s{%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
|
||||
padding1,nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
|
||||
else
|
||||
txt=sprintf('%s"%s": {%s%s"_ArrayType_": "%s",%s%s"_ArraySize_": %s,%s',...
|
||||
padding1,checkname(name,varargin{:}),nl,padding0,class(item),nl,padding0,regexprep(mat2str(size(item)),'\s+',','),nl);
|
||||
end
|
||||
else
|
||||
if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0 && level>0)
|
||||
numtxt=regexprep(regexprep(matdata2json(item,level+1,varargin{:}),'^\[',''),']$','');
|
||||
else
|
||||
numtxt=matdata2json(item,level+1,varargin{:});
|
||||
end
|
||||
if(isempty(name))
|
||||
txt=sprintf('%s%s',padding1,numtxt);
|
||||
else
|
||||
if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0)
|
||||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
|
||||
else
|
||||
txt=sprintf('%s"%s": %s',padding1,checkname(name,varargin{:}),numtxt);
|
||||
end
|
||||
end
|
||||
return;
|
||||
end
|
||||
dataformat='%s%s%s%s%s';
|
||||
|
||||
if(issparse(item))
|
||||
[ix,iy]=find(item);
|
||||
data=full(item(find(item)));
|
||||
if(~isreal(item))
|
||||
data=[real(data(:)),imag(data(:))];
|
||||
if(size(item,1)==1)
|
||||
% Kludge to have data's 'transposedness' match item's.
|
||||
% (Necessary for complex row vector handling below.)
|
||||
data=data';
|
||||
end
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
|
||||
end
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsSparse_": ','1', sep);
|
||||
if(~isempty(dozip) && numel(data*2)>zipsize)
|
||||
if(size(item,1)==1)
|
||||
% Row vector, store only column indices.
|
||||
fulldata=[iy(:),data'];
|
||||
elseif(size(item,2)==1)
|
||||
% Column vector, store only row indices.
|
||||
fulldata=[ix,data];
|
||||
else
|
||||
% General case, store row and column indices.
|
||||
fulldata=[ix,iy,data];
|
||||
end
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressionSize_": ',regexprep(mat2str(size(fulldata)),'\s+',','), sep);
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressionMethod_": "',dozip, ['"' sep]);
|
||||
if(strcmpi(dozip,'gzip'))
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressedData_": "',base64encode(gzipencode(typecast(fulldata(:),'uint8'))),['"' nl]);
|
||||
elseif(strcmpi(dozip,'zlib'))
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressedData_": "',base64encode(zlibencode(typecast(fulldata(:),'uint8'))),['"' nl]);
|
||||
else
|
||||
error('compression method not supported');
|
||||
end
|
||||
else
|
||||
if(size(item,1)==1)
|
||||
% Row vector, store only column indices.
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
||||
matdata2json([iy(:),data'],level+2,varargin{:}), nl);
|
||||
elseif(size(item,2)==1)
|
||||
% Column vector, store only row indices.
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
||||
matdata2json([ix,data],level+2,varargin{:}), nl);
|
||||
else
|
||||
% General case, store row and column indices.
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
||||
matdata2json([ix,iy,data],level+2,varargin{:}), nl);
|
||||
end
|
||||
end
|
||||
else
|
||||
if(~isempty(dozip) && numel(item)>zipsize)
|
||||
if(isreal(item))
|
||||
fulldata=item(:)';
|
||||
if(islogical(fulldata))
|
||||
fulldata=uint8(fulldata);
|
||||
end
|
||||
else
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
|
||||
fulldata=[real(item(:)) imag(item(:))];
|
||||
end
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressionSize_": ',regexprep(mat2str(size(fulldata)),'\s+',','), sep);
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressionMethod_": "',dozip, ['"' sep]);
|
||||
if(strcmpi(dozip,'gzip'))
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressedData_": "',base64encode(gzipencode(typecast(fulldata(:),'uint8'))),['"' nl]);
|
||||
elseif(strcmpi(dozip,'zlib'))
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayCompressedData_": "',base64encode(zlibencode(typecast(fulldata(:),'uint8'))),['"' nl]);
|
||||
else
|
||||
error('compression method not supported');
|
||||
end
|
||||
else
|
||||
if(isreal(item))
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
||||
matdata2json(item(:)',level+2,varargin{:}), nl);
|
||||
else
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayIsComplex_": ','1', sep);
|
||||
txt=sprintf(dataformat,txt,padding0,'"_ArrayData_": ',...
|
||||
matdata2json([real(item(:)) imag(item(:))],level+2,varargin{:}), nl);
|
||||
end
|
||||
end
|
||||
end
|
||||
txt=sprintf('%s%s%s',txt,padding1,'}');
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=matlabobject2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
if numel(item) == 0 %empty object
|
||||
st = struct();
|
||||
elseif numel(item) == 1 %
|
||||
st = struct();
|
||||
txt = str2json(name, char(item), level, varargin(:));
|
||||
return
|
||||
else
|
||||
% "st = struct(item);" would produce an inmutable warning, because it
|
||||
% make the protected and private properties visible. Instead we get the
|
||||
% visible properties
|
||||
propertynames = properties(item);
|
||||
for p = 1:numel(propertynames)
|
||||
for o = numel(item):-1:1 % aray of objects
|
||||
st(o).(propertynames{p}) = item(o).(propertynames{p});
|
||||
end
|
||||
end
|
||||
end
|
||||
txt=struct2json(name,st,level,varargin{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=matlabtable2json(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
if numel(item) == 0 %empty object
|
||||
st = struct();
|
||||
else
|
||||
% "st = struct(item);" would produce an inmutable warning, because it
|
||||
% make the protected and private properties visible. Instead we get the
|
||||
% visible properties
|
||||
st = struct();
|
||||
propertynames = properties(item);
|
||||
if(isfield(item.Properties,'RowNames') && ~isempty(item.Properties.RowNames))
|
||||
rownames=item.Properties.RowNames;
|
||||
for p = 1:(numel(propertynames)-1)
|
||||
for j = 1:size(item(:,p),1)
|
||||
st.(rownames{j}).(propertynames{p}) = item{j,p};
|
||||
end
|
||||
end
|
||||
else
|
||||
for p = 1:(numel(propertynames)-1)
|
||||
for j = 1:size(item(:,p),1)
|
||||
st(j).(propertynames{p}) = item{j,p};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
txt=struct2json(name,st,level,varargin{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=matdata2json(mat,level,varargin)
|
||||
import jsonlab.*
|
||||
|
||||
ws=struct('tab',sprintf('\t'),'newline',sprintf('\n'),'sep',sprintf(',\n'));
|
||||
ws=jsonopt('whitespaces_',ws,varargin{:});
|
||||
tab=ws.tab;
|
||||
nl=ws.newline;
|
||||
|
||||
if(size(mat,1)==1)
|
||||
pre='';
|
||||
post='';
|
||||
level=level-1;
|
||||
else
|
||||
pre=sprintf('[%s',nl);
|
||||
post=sprintf('%s%s]',nl,repmat(tab,1,level-1));
|
||||
end
|
||||
|
||||
if(isempty(mat))
|
||||
txt='null';
|
||||
return;
|
||||
end
|
||||
if(isinteger(mat))
|
||||
floatformat=jsonopt('FloatFormat','%d',varargin{:});
|
||||
else
|
||||
floatformat=jsonopt('FloatFormat','%.10g',varargin{:});
|
||||
end
|
||||
%if(numel(mat)>1)
|
||||
formatstr=['[' repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf('],%s',nl)]];
|
||||
%else
|
||||
% formatstr=[repmat([floatformat ','],1,size(mat,2)-1) [floatformat sprintf(',\n')]];
|
||||
%end
|
||||
|
||||
if(nargin>=2 && size(mat,1)>1 && jsonopt('ArrayIndent',1,varargin{:})==1)
|
||||
formatstr=[repmat(tab,1,level) formatstr];
|
||||
end
|
||||
|
||||
txt=sprintf(formatstr,mat');
|
||||
txt(end-length(nl):end)=[];
|
||||
if(islogical(mat) && jsonopt('ParseLogical',0,varargin{:})==1)
|
||||
txt=regexprep(txt,'1','true');
|
||||
txt=regexprep(txt,'0','false');
|
||||
end
|
||||
%txt=regexprep(mat2str(mat),'\s+',',');
|
||||
%txt=regexprep(txt,';',sprintf('],\n['));
|
||||
% if(nargin>=2 && size(mat,1)>1)
|
||||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']);
|
||||
% end
|
||||
txt=[pre txt post];
|
||||
if(any(isinf(mat(:))))
|
||||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:}));
|
||||
end
|
||||
if(any(isnan(mat(:))))
|
||||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:}));
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function newname=checkname(name,varargin)
|
||||
import jsonlab.*
|
||||
isunpack=jsonopt('UnpackHex',1,varargin{:});
|
||||
newname=name;
|
||||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once')))
|
||||
return
|
||||
end
|
||||
if(isunpack)
|
||||
isoct=jsonopt('IsOctave',0,varargin{:});
|
||||
if(~isoct)
|
||||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}');
|
||||
else
|
||||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start');
|
||||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end');
|
||||
if(isempty(pos))
|
||||
return;
|
||||
end
|
||||
str0=name;
|
||||
pos0=[0 pend(:)' length(name)];
|
||||
newname='';
|
||||
for i=1:length(pos)
|
||||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))];
|
||||
end
|
||||
if(pos(end)~=length(name))
|
||||
newname=[newname str0(pos0(end-1)+1:pos0(end))];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function newstr=escapejsonstring(str)
|
||||
import jsonlab.*
|
||||
newstr=str;
|
||||
isoct=exist('OCTAVE_VERSION','builtin');
|
||||
if(isoct)
|
||||
vv=sscanf(OCTAVE_VERSION,'%f');
|
||||
if(vv(1)>=3.8)
|
||||
isoct=0;
|
||||
end
|
||||
end
|
||||
if(isoct)
|
||||
escapechars={'\\','\"','\/','\a','\f','\n','\r','\t','\v'};
|
||||
for i=1:length(escapechars);
|
||||
newstr=regexprep(newstr,escapechars{i},escapechars{i});
|
||||
end
|
||||
newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\$1');
|
||||
else
|
||||
escapechars={'\\','\"','\/','\a','\b','\f','\n','\r','\t','\v'};
|
||||
for i=1:length(escapechars);
|
||||
newstr=regexprep(newstr,escapechars{i},regexprep(escapechars{i},'\\','\\\\'));
|
||||
end
|
||||
newstr=regexprep(newstr,'\\\\(u[0-9a-fA-F]{4}[^0-9a-fA-F]*)','\\$1');
|
||||
end
|
||||
|
|
@ -0,0 +1,663 @@
|
|||
function json=saveubjson(rootname,obj,varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% json=saveubjson(rootname,obj,filename)
|
||||
% or
|
||||
% json=saveubjson(rootname,obj,opt)
|
||||
% json=saveubjson(rootname,obj,'param1',value1,'param2',value2,...)
|
||||
%
|
||||
% convert a MATLAB object (cell, struct or array) into a Universal
|
||||
% Binary JSON (UBJSON) binary string
|
||||
%
|
||||
% author: Qianqian Fang (q.fang <at> neu.edu)
|
||||
% created on 2013/08/17
|
||||
%
|
||||
% $Id$
|
||||
%
|
||||
% input:
|
||||
% rootname: the name of the root-object, when set to '', the root name
|
||||
% is ignored, however, when opt.ForceRootName is set to 1 (see below),
|
||||
% the MATLAB variable name will be used as the root name.
|
||||
% obj: a MATLAB object (array, cell, cell array, struct, struct array,
|
||||
% class instance)
|
||||
% filename: a string for the file name to save the output UBJSON data
|
||||
% opt: a struct for additional options, ignore to use default values.
|
||||
% opt can have the following fields (first in [.|.] is the default)
|
||||
%
|
||||
% opt.FileName [''|string]: a file name to save the output JSON data
|
||||
% opt.ArrayToStruct[0|1]: when set to 0, saveubjson outputs 1D/2D
|
||||
% array in JSON array format; if sets to 1, an
|
||||
% array will be shown as a struct with fields
|
||||
% "_ArrayType_", "_ArraySize_" and "_ArrayData_"; for
|
||||
% sparse arrays, the non-zero elements will be
|
||||
% saved to _ArrayData_ field in triplet-format i.e.
|
||||
% (ix,iy,val) and "_ArrayIsSparse_" will be added
|
||||
% with a value of 1; for a complex array, the
|
||||
% _ArrayData_ array will include two columns
|
||||
% (4 for sparse) to record the real and imaginary
|
||||
% parts, and also "_ArrayIsComplex_":1 is added.
|
||||
% opt.ParseLogical [1|0]: if this is set to 1, logical array elem
|
||||
% will use true/false rather than 1/0.
|
||||
% opt.SingletArray [0|1]: if this is set to 1, arrays with a single
|
||||
% numerical element will be shown without a square
|
||||
% bracket, unless it is the root object; if 0, square
|
||||
% brackets are forced for any numerical arrays.
|
||||
% opt.SingletCell [1|0]: if 1, always enclose a cell with "[]"
|
||||
% even it has only one element; if 0, brackets
|
||||
% are ignored when a cell has only 1 element.
|
||||
% opt.ForceRootName [0|1]: when set to 1 and rootname is empty, saveubjson
|
||||
% will use the name of the passed obj variable as the
|
||||
% root object name; if obj is an expression and
|
||||
% does not have a name, 'root' will be used; if this
|
||||
% is set to 0 and rootname is empty, the root level
|
||||
% will be merged down to the lower level.
|
||||
% opt.JSONP [''|string]: to generate a JSONP output (JSON with padding),
|
||||
% for example, if opt.JSON='foo', the JSON data is
|
||||
% wrapped inside a function call as 'foo(...);'
|
||||
% opt.UnpackHex [1|0]: conver the 0x[hex code] output by loadjson
|
||||
% back to the string form
|
||||
% opt.Compression 'zlib' or 'gzip': specify array compression
|
||||
% method; currently only supports 'gzip' or 'zlib'. The
|
||||
% data compression only applicable to numerical arrays
|
||||
% in 3D or higher dimensions, or when ArrayToStruct
|
||||
% is 1 for 1D or 2D arrays. If one wants to
|
||||
% compress a long string, one must convert
|
||||
% it to uint8 or int8 array first. The compressed
|
||||
% array uses three extra fields
|
||||
% "_ArrayCompressionMethod_": the opt.Compression value.
|
||||
% "_ArrayCompressionSize_": a 1D interger array to
|
||||
% store the pre-compressed (but post-processed)
|
||||
% array dimensions, and
|
||||
% "_ArrayCompressedData_": the binary stream of
|
||||
% the compressed binary array data WITHOUT
|
||||
% 'base64' encoding
|
||||
% opt.CompressArraySize [100|int]: only to compress an array if the total
|
||||
% element count is larger than this number.
|
||||
%
|
||||
% opt can be replaced by a list of ('param',value) pairs. The param
|
||||
% string is equivallent to a field in opt and is case sensitive.
|
||||
% output:
|
||||
% json: a binary string in the UBJSON format (see http://ubjson.org)
|
||||
%
|
||||
% examples:
|
||||
% jsonmesh=struct('MeshNode',[0 0 0;1 0 0;0 1 0;1 1 0;0 0 1;1 0 1;0 1 1;1 1 1],...
|
||||
% 'MeshTetra',[1 2 4 8;1 3 4 8;1 2 6 8;1 5 6 8;1 5 7 8;1 3 7 8],...
|
||||
% 'MeshTri',[1 2 4;1 2 6;1 3 4;1 3 7;1 5 6;1 5 7;...
|
||||
% 2 8 4;2 8 6;3 8 4;3 8 7;5 8 6;5 8 7],...
|
||||
% 'MeshCreator','FangQ','MeshTitle','T6 Cube',...
|
||||
% 'SpecialData',[nan, inf, -inf]);
|
||||
% saveubjson('jsonmesh',jsonmesh)
|
||||
% saveubjson('jsonmesh',jsonmesh,'meshdata.ubj')
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
if(nargin==1)
|
||||
varname=inputname(1);
|
||||
obj=rootname;
|
||||
if(isempty(varname))
|
||||
varname='root';
|
||||
end
|
||||
rootname=varname;
|
||||
else
|
||||
varname=inputname(2);
|
||||
end
|
||||
if(length(varargin)==1 && ischar(varargin{1}))
|
||||
opt=struct('filename',varargin{1});
|
||||
else
|
||||
opt=varargin2struct(varargin{:});
|
||||
end
|
||||
opt.IsOctave=exist('OCTAVE_VERSION','builtin');
|
||||
|
||||
dozip=jsonopt('Compression','',opt);
|
||||
if(~isempty(dozip))
|
||||
if(~(strcmpi(dozip,'gzip') || strcmpi(dozip,'zlib')))
|
||||
error('compression method "%s" is not supported',dozip);
|
||||
end
|
||||
if(exist('zmat')~=3)
|
||||
try
|
||||
error(javachk('jvm'));
|
||||
try
|
||||
base64decode('test');
|
||||
catch
|
||||
matlab.net.base64decode('test');
|
||||
end
|
||||
catch
|
||||
error('java-based compression is not supported');
|
||||
end
|
||||
end
|
||||
opt.Compression=dozip;
|
||||
end
|
||||
|
||||
if(isfield(opt,'norowbracket'))
|
||||
warning('Option ''NoRowBracket'' is depreciated, please use ''SingletArray'' and set its value to not(NoRowBracket)');
|
||||
if(~isfield(opt,'singletarray'))
|
||||
opt.singletarray=not(opt.norowbracket);
|
||||
end
|
||||
end
|
||||
rootisarray=0;
|
||||
rootlevel=1;
|
||||
forceroot=jsonopt('ForceRootName',0,opt);
|
||||
if((isnumeric(obj) || islogical(obj) || ischar(obj) || isstruct(obj) || ...
|
||||
iscell(obj) || isobject(obj)) && isempty(rootname) && forceroot==0)
|
||||
rootisarray=1;
|
||||
rootlevel=0;
|
||||
else
|
||||
if(isempty(rootname))
|
||||
rootname=varname;
|
||||
end
|
||||
end
|
||||
if((isstruct(obj) || iscell(obj))&& isempty(rootname) && forceroot)
|
||||
rootname='root';
|
||||
end
|
||||
json=obj2ubjson(rootname,obj,rootlevel,opt);
|
||||
if(~rootisarray)
|
||||
json=['{' json '}'];
|
||||
end
|
||||
|
||||
jsonp=jsonopt('JSONP','',opt);
|
||||
if(~isempty(jsonp))
|
||||
json=[jsonp '(' json ')'];
|
||||
end
|
||||
|
||||
% save to a file if FileName is set, suggested by Patrick Rapin
|
||||
filename=jsonopt('FileName','',opt);
|
||||
if(~isempty(filename))
|
||||
fid = fopen(filename, 'wb');
|
||||
fwrite(fid,json);
|
||||
fclose(fid);
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=obj2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
|
||||
if(iscell(item))
|
||||
txt=cell2ubjson(name,item,level,varargin{:});
|
||||
elseif(isstruct(item))
|
||||
txt=struct2ubjson(name,item,level,varargin{:});
|
||||
elseif(ischar(item))
|
||||
txt=str2ubjson(name,item,level,varargin{:});
|
||||
elseif(isobject(item))
|
||||
txt=matlabobject2ubjson(name,item,level,varargin{:});
|
||||
else
|
||||
txt=mat2ubjson(name,item,level,varargin{:});
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=cell2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt='';
|
||||
if(~iscell(item))
|
||||
error('input is not a cell');
|
||||
end
|
||||
|
||||
dim=size(item);
|
||||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
||||
item=reshape(item,dim(1),numel(item)/dim(1));
|
||||
dim=size(item);
|
||||
end
|
||||
bracketlevel=~jsonopt('singletcell',1,varargin{:});
|
||||
len=numel(item); % let's handle 1D cell first
|
||||
if(len>bracketlevel)
|
||||
if(~isempty(name))
|
||||
txt=[N_(checkname(name,varargin{:})) '[']; name='';
|
||||
else
|
||||
txt='[';
|
||||
end
|
||||
elseif(len==0)
|
||||
if(~isempty(name))
|
||||
txt=[N_(checkname(name,varargin{:})) 'Z']; name='';
|
||||
else
|
||||
txt='Z';
|
||||
end
|
||||
end
|
||||
for j=1:dim(2)
|
||||
if(dim(1)>1)
|
||||
txt=[txt '['];
|
||||
end
|
||||
for i=1:dim(1)
|
||||
txt=[txt obj2ubjson(name,item{i,j},level+(len>bracketlevel),varargin{:})];
|
||||
end
|
||||
if(dim(1)>1)
|
||||
txt=[txt ']'];
|
||||
end
|
||||
end
|
||||
if(len>bracketlevel)
|
||||
txt=[txt ']'];
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=struct2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt='';
|
||||
if(~isstruct(item))
|
||||
error('input is not a struct');
|
||||
end
|
||||
dim=size(item);
|
||||
if(ndims(squeeze(item))>2) % for 3D or higher dimensions, flatten to 2D for now
|
||||
item=reshape(item,dim(1),numel(item)/dim(1));
|
||||
dim=size(item);
|
||||
end
|
||||
len=numel(item);
|
||||
forcearray= (len>1 || (jsonopt('SingletArray',0,varargin{:})==1 && level>0));
|
||||
|
||||
if(~isempty(name))
|
||||
if(forcearray)
|
||||
txt=[N_(checkname(name,varargin{:})) '['];
|
||||
end
|
||||
else
|
||||
if(forcearray)
|
||||
txt='[';
|
||||
end
|
||||
end
|
||||
for j=1:dim(2)
|
||||
if(dim(1)>1)
|
||||
txt=[txt '['];
|
||||
end
|
||||
for i=1:dim(1)
|
||||
names = fieldnames(item(i,j));
|
||||
if(~isempty(name) && len==1 && ~forcearray)
|
||||
txt=[txt N_(checkname(name,varargin{:})) '{'];
|
||||
else
|
||||
txt=[txt '{'];
|
||||
end
|
||||
if(~isempty(names))
|
||||
for e=1:length(names)
|
||||
txt=[txt obj2ubjson(names{e},item(i,j).(names{e}),...
|
||||
level+(dim(1)>1)+1+forcearray,varargin{:})];
|
||||
end
|
||||
end
|
||||
txt=[txt '}'];
|
||||
end
|
||||
if(dim(1)>1)
|
||||
txt=[txt ']'];
|
||||
end
|
||||
end
|
||||
if(forcearray)
|
||||
txt=[txt ']'];
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=str2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
txt='';
|
||||
if(~ischar(item))
|
||||
error('input is not a string');
|
||||
end
|
||||
item=reshape(item, max(size(item),[1 0]));
|
||||
len=size(item,1);
|
||||
|
||||
if(~isempty(name))
|
||||
if(len>1)
|
||||
txt=[N_(checkname(name,varargin{:})) '['];
|
||||
end
|
||||
else
|
||||
if(len>1)
|
||||
txt='[';
|
||||
end
|
||||
end
|
||||
for e=1:len
|
||||
val=item(e,:);
|
||||
if(len==1)
|
||||
obj=[N_(checkname(name,varargin{:})) '' '',S_(val),''];
|
||||
if(isempty(name))
|
||||
obj=['',S_(val),''];
|
||||
end
|
||||
txt=[txt,'',obj];
|
||||
else
|
||||
txt=[txt,'',['',S_(val),'']];
|
||||
end
|
||||
end
|
||||
if(len>1)
|
||||
txt=[txt ']'];
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=mat2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
if(~isnumeric(item) && ~islogical(item))
|
||||
error('input is not an array');
|
||||
end
|
||||
|
||||
dozip=jsonopt('Compression','',varargin{:});
|
||||
zipsize=jsonopt('CompressArraySize',100,varargin{:});
|
||||
|
||||
if(length(size(item))>2 || issparse(item) || ~isreal(item) || ...
|
||||
(isempty(item) && any(size(item))) ||jsonopt('ArrayToStruct',0,varargin{:}) || (~isempty(dozip) && numel(item)>zipsize))
|
||||
cid=I_(uint32(max(size(item))));
|
||||
if(isempty(name))
|
||||
txt=['{' N_('_ArrayType_'),S_(class(item)),N_('_ArraySize_'),I_a(size(item),cid(1)) ];
|
||||
else
|
||||
if(isempty(item))
|
||||
txt=[N_(checkname(name,varargin{:})),'Z'];
|
||||
return;
|
||||
else
|
||||
txt=[N_(checkname(name,varargin{:})),'{',N_('_ArrayType_'),S_(class(item)),N_('_ArraySize_'),I_a(size(item),cid(1))];
|
||||
end
|
||||
end
|
||||
else
|
||||
if(isempty(name))
|
||||
txt=matdata2ubjson(item,level+1,varargin{:});
|
||||
else
|
||||
if(numel(item)==1 && jsonopt('SingletArray',0,varargin{:})==0)
|
||||
numtxt=regexprep(regexprep(matdata2ubjson(item,level+1,varargin{:}),'^\[',''),']$','');
|
||||
txt=[N_(checkname(name,varargin{:})) numtxt];
|
||||
else
|
||||
txt=[N_(checkname(name,varargin{:})),matdata2ubjson(item,level+1,varargin{:})];
|
||||
end
|
||||
end
|
||||
return;
|
||||
end
|
||||
if(issparse(item))
|
||||
[ix,iy]=find(item);
|
||||
data=full(item(find(item)));
|
||||
if(~isreal(item))
|
||||
data=[real(data(:)),imag(data(:))];
|
||||
if(size(item,1)==1)
|
||||
% Kludge to have data's 'transposedness' match item's.
|
||||
% (Necessary for complex row vector handling below.)
|
||||
data=data';
|
||||
end
|
||||
txt=[txt,N_('_ArrayIsComplex_'),'T'];
|
||||
end
|
||||
txt=[txt,N_('_ArrayIsSparse_'),'T'];
|
||||
if(~isempty(dozip) && numel(data*2)>zipsize)
|
||||
if(size(item,1)==1)
|
||||
% Row vector, store only column indices.
|
||||
fulldata=[iy(:),data'];
|
||||
elseif(size(item,2)==1)
|
||||
% Column vector, store only row indices.
|
||||
fulldata=[ix,data];
|
||||
else
|
||||
% General case, store row and column indices.
|
||||
fulldata=[ix,iy,data];
|
||||
end
|
||||
cid=I_(uint32(max(size(fulldata))));
|
||||
txt=[txt, N_('_ArrayCompressionSize_'),I_a(size(fulldata),cid(1))];
|
||||
txt=[txt, N_('_ArrayCompressionMethod_'),S_(dozip)];
|
||||
if(strcmpi(dozip,'gzip'))
|
||||
txt=[txt,N_('_ArrayCompressedData_'), I_a(gzipencode(typecast(fulldata(:),'uint8')),'U')];
|
||||
elseif(strcmpi(dozip,'zlib'))
|
||||
txt=[txt,N_('_ArrayCompressedData_'), I_a(zlibencode(typecast(fulldata(:),'uint8')),'U')];
|
||||
else
|
||||
error('compression method not supported');
|
||||
end
|
||||
else
|
||||
if(size(item,1)==1)
|
||||
% Row vector, store only column indices.
|
||||
txt=[txt,N_('_ArrayData_'),...
|
||||
matdata2ubjson([iy(:),data'],level+2,varargin{:})];
|
||||
elseif(size(item,2)==1)
|
||||
% Column vector, store only row indices.
|
||||
txt=[txt,N_('_ArrayData_'),...
|
||||
matdata2ubjson([ix,data],level+2,varargin{:})];
|
||||
else
|
||||
% General case, store row and column indices.
|
||||
txt=[txt,N_('_ArrayData_'),...
|
||||
matdata2ubjson([ix,iy,data],level+2,varargin{:})];
|
||||
end
|
||||
end
|
||||
else
|
||||
if(~isempty(dozip) && numel(item)>zipsize)
|
||||
if(isreal(item))
|
||||
fulldata=item(:)';
|
||||
if(islogical(fulldata))
|
||||
fulldata=uint8(fulldata);
|
||||
end
|
||||
else
|
||||
txt=[txt,N_('_ArrayIsComplex_'),'T'];
|
||||
fulldata=[real(item(:)) imag(item(:))];
|
||||
end
|
||||
cid=I_(uint32(max(size(fulldata))));
|
||||
txt=[txt, N_('_ArrayCompressionSize_'),I_a(size(fulldata),cid(1))];
|
||||
txt=[txt, N_('_ArrayCompressionMethod_'),S_(dozip)];
|
||||
if(strcmpi(dozip,'gzip'))
|
||||
txt=[txt,N_('_ArrayCompressedData_'), I_a(gzipencode(typecast(fulldata(:),'uint8')),'U')];
|
||||
elseif(strcmpi(dozip,'zlib'))
|
||||
txt=[txt,N_('_ArrayCompressedData_'), I_a(zlibencode(typecast(fulldata(:),'uint8')),'U')];
|
||||
else
|
||||
error('compression method not supported');
|
||||
end
|
||||
else
|
||||
if(isreal(item))
|
||||
txt=[txt,N_('_ArrayData_'),...
|
||||
matdata2ubjson(item(:)',level+2,varargin{:})];
|
||||
else
|
||||
txt=[txt,N_('_ArrayIsComplex_'),'T'];
|
||||
txt=[txt,N_('_ArrayData_'),...
|
||||
matdata2ubjson([real(item(:)) imag(item(:))],level+2,varargin{:})];
|
||||
end
|
||||
end
|
||||
end
|
||||
txt=[txt,'}'];
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=matlabobject2ubjson(name,item,level,varargin)
|
||||
import jsonlab.*
|
||||
st = struct();
|
||||
if numel(item) > 0 %non-empty object
|
||||
% "st = struct(item);" would produce an inmutable warning, because it
|
||||
% make the protected and private properties visible. Instead we get the
|
||||
% visible properties
|
||||
propertynames = properties(item);
|
||||
for p = 1:numel(propertynames)
|
||||
for o = numel(item):-1:1 % aray of objects
|
||||
st(o).(propertynames{p}) = item(o).(propertynames{p});
|
||||
end
|
||||
end
|
||||
end
|
||||
txt=struct2ubjson(name,st,level,varargin{:});
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function txt=matdata2ubjson(mat,level,varargin)
|
||||
import jsonlab.*
|
||||
if(isempty(mat))
|
||||
txt='Z';
|
||||
return;
|
||||
end
|
||||
type='';
|
||||
hasnegtive=(mat<0);
|
||||
if(isa(mat,'integer') || isinteger(mat) || (isfloat(mat) && all(mod(mat(:),1) == 0)))
|
||||
if(isempty(hasnegtive))
|
||||
if(max(mat(:))<=2^8)
|
||||
type='U';
|
||||
end
|
||||
end
|
||||
if(isempty(type))
|
||||
% todo - need to consider negative ones separately
|
||||
id= histc(abs(max(double(mat(:)))),[0 2^7 2^15 2^31 2^63]);
|
||||
if(isempty(id~=0))
|
||||
error('high-precision data is not yet supported');
|
||||
end
|
||||
key='iIlL';
|
||||
type=key(id~=0);
|
||||
end
|
||||
txt=[I_a(mat(:),type,size(mat))];
|
||||
elseif(islogical(mat))
|
||||
logicalval='FT';
|
||||
if(numel(mat)==1)
|
||||
txt=logicalval(mat+1);
|
||||
else
|
||||
txt=['[$U#' I_a(size(mat),'l') typecast(swapbytes(uint8(mat(:)')),'uint8')];
|
||||
end
|
||||
else
|
||||
if(numel(mat)==1)
|
||||
txt=['[' D_(mat) ']'];
|
||||
else
|
||||
txt=D_a(mat(:),'D',size(mat));
|
||||
end
|
||||
end
|
||||
|
||||
%txt=regexprep(mat2str(mat),'\s+',',');
|
||||
%txt=regexprep(txt,';',sprintf('],['));
|
||||
% if(nargin>=2 && size(mat,1)>1)
|
||||
% txt=regexprep(txt,'\[',[repmat(sprintf('\t'),1,level) '[']);
|
||||
% end
|
||||
if(any(isinf(mat(:))))
|
||||
txt=regexprep(txt,'([-+]*)Inf',jsonopt('Inf','"$1_Inf_"',varargin{:}));
|
||||
end
|
||||
if(any(isnan(mat(:))))
|
||||
txt=regexprep(txt,'NaN',jsonopt('NaN','"_NaN_"',varargin{:}));
|
||||
end
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function newname=checkname(name,varargin)
|
||||
import jsonlab.*
|
||||
isunpack=jsonopt('UnpackHex',1,varargin{:});
|
||||
newname=name;
|
||||
if(isempty(regexp(name,'0x([0-9a-fA-F]+)_','once')))
|
||||
return
|
||||
end
|
||||
if(isunpack)
|
||||
isoct=jsonopt('IsOctave',0,varargin{:});
|
||||
if(~isoct)
|
||||
newname=regexprep(name,'(^x|_){1}0x([0-9a-fA-F]+)_','${native2unicode(hex2dec($2))}');
|
||||
else
|
||||
pos=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','start');
|
||||
pend=regexp(name,'(^x|_){1}0x([0-9a-fA-F]+)_','end');
|
||||
if(isempty(pos))
|
||||
return;
|
||||
end
|
||||
str0=name;
|
||||
pos0=[0 pend(:)' length(name)];
|
||||
newname='';
|
||||
for i=1:length(pos)
|
||||
newname=[newname str0(pos0(i)+1:pos(i)-1) char(hex2dec(str0(pos(i)+3:pend(i)-1)))];
|
||||
end
|
||||
if(pos(end)~=length(name))
|
||||
newname=[newname str0(pos0(end-1)+1:pos0(end))];
|
||||
end
|
||||
end
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
function val=N_(str)
|
||||
import jsonlab.*
|
||||
val=[I_(int32(length(str))) str];
|
||||
%%-------------------------------------------------------------------------
|
||||
function val=S_(str)
|
||||
import jsonlab.*
|
||||
if(length(str)==1)
|
||||
val=['C' str];
|
||||
else
|
||||
val=['S' I_(int32(length(str))) str];
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
function val=I_(num)
|
||||
import jsonlab.*
|
||||
if(~isinteger(num))
|
||||
error('input is not an integer');
|
||||
end
|
||||
if(num>=0 && num<255)
|
||||
val=['U' data2byte(swapbytes(cast(num,'uint8')),'uint8')];
|
||||
return;
|
||||
end
|
||||
key='iIlL';
|
||||
cid={'int8','int16','int32','int64'};
|
||||
for i=1:4
|
||||
if((num>0 && num<2^(i*8-1)) || (num<0 && num>=-2^(i*8-1)))
|
||||
val=[key(i) data2byte(swapbytes(cast(num,cid{i})),'uint8')];
|
||||
return;
|
||||
end
|
||||
end
|
||||
error('unsupported integer');
|
||||
|
||||
%%-------------------------------------------------------------------------
|
||||
function val=D_(num)
|
||||
import jsonlab.*
|
||||
if(~isfloat(num))
|
||||
error('input is not a float');
|
||||
end
|
||||
|
||||
if(isa(num,'single'))
|
||||
val=['d' data2byte(swapbytes(num),'uint8')];
|
||||
else
|
||||
val=['D' data2byte(swapbytes(num),'uint8')];
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
function data=I_a(num,type,dim,format)
|
||||
import jsonlab.*
|
||||
id=find(ismember('iUIlL',type));
|
||||
|
||||
if(id==0)
|
||||
error('unsupported integer array');
|
||||
end
|
||||
|
||||
% based on UBJSON specs, all integer types are stored in big endian format
|
||||
|
||||
if(id==1)
|
||||
data=data2byte(swapbytes(int8(num)),'uint8');
|
||||
blen=1;
|
||||
elseif(id==2)
|
||||
data=data2byte(swapbytes(uint8(num)),'uint8');
|
||||
blen=1;
|
||||
elseif(id==3)
|
||||
data=data2byte(swapbytes(int16(num)),'uint8');
|
||||
blen=2;
|
||||
elseif(id==4)
|
||||
data=data2byte(swapbytes(int32(num)),'uint8');
|
||||
blen=4;
|
||||
elseif(id==5)
|
||||
data=data2byte(swapbytes(int64(num)),'uint8');
|
||||
blen=8;
|
||||
end
|
||||
|
||||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2))
|
||||
format='opt';
|
||||
end
|
||||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1)
|
||||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2))))
|
||||
cid=I_(uint32(max(dim)));
|
||||
data=['$' type '#' I_a(dim,cid(1)) data(:)'];
|
||||
else
|
||||
data=['$' type '#' I_(int32(numel(data)/blen)) data(:)'];
|
||||
end
|
||||
data=['[' data(:)'];
|
||||
else
|
||||
data=reshape(data,blen,numel(data)/blen);
|
||||
data(2:blen+1,:)=data;
|
||||
data(1,:)=type;
|
||||
data=data(:)';
|
||||
data=['[' data(:)' ']'];
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
function data=D_a(num,type,dim,format)
|
||||
import jsonlab.*
|
||||
id=find(ismember('dD',type));
|
||||
|
||||
if(id==0)
|
||||
error('unsupported float array');
|
||||
end
|
||||
|
||||
if(id==1)
|
||||
data=data2byte(swapbytes(single(num)),'uint8');
|
||||
elseif(id==2)
|
||||
data=data2byte(swapbytes(double(num)),'uint8');
|
||||
end
|
||||
|
||||
if(nargin>=3 && length(dim)>=2 && prod(dim)~=dim(2))
|
||||
format='opt';
|
||||
end
|
||||
if((nargin<4 || strcmp(format,'opt')) && numel(num)>1)
|
||||
if(nargin>=3 && (length(dim)==1 || (length(dim)>=2 && prod(dim)~=dim(2))))
|
||||
cid=I_(uint32(max(dim)));
|
||||
data=['$' type '#' I_a(dim,cid(1)) data(:)'];
|
||||
else
|
||||
data=['$' type '#' I_(int32(numel(data)/(id*4))) data(:)'];
|
||||
end
|
||||
data=['[' data];
|
||||
else
|
||||
data=reshape(data,(id*4),length(data)/(id*4));
|
||||
data(2:(id*4+1),:)=data;
|
||||
data(1,:)=type;
|
||||
data=data(:)';
|
||||
data=['[' data(:)' ']'];
|
||||
end
|
||||
%%-------------------------------------------------------------------------
|
||||
function bytes=data2byte(varargin)
|
||||
import jsonlab.*
|
||||
bytes=typecast(varargin{:});
|
||||
bytes=char(bytes(:)');
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
function newdata=struct2jdata(data,varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% newdata=struct2jdata(data,opt,...)
|
||||
%
|
||||
% convert a JData object (in the form of a struct array) into an array
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
%
|
||||
% input:
|
||||
% data: a struct array. If data contains JData keywords in the first
|
||||
% level children, these fields are parsed and regrouped into a
|
||||
% data object (arrays, trees, graphs etc) based on JData
|
||||
% specification. The JData keywords are
|
||||
% "_ArrayType_", "_ArraySize_", "_ArrayData_"
|
||||
% "_ArrayIsSparse_", "_ArrayIsComplex_",
|
||||
% "_ArrayCompressionMethod_", "_ArrayCompressionSize",
|
||||
% "_ArrayCompressedData_"
|
||||
% opt: (optional) a list of 'Param',value pairs for additional options
|
||||
% The supported options include
|
||||
% 'Recursive', if set to 1, will apply the conversion to
|
||||
% every child; 0 to disable
|
||||
% 'Base64'. if set to 1, _ArrayCompressedData_ is assumed to
|
||||
% be encoded with base64 format and need to be
|
||||
% decoded first. This is needed for JSON but not
|
||||
% UBJSON data
|
||||
%
|
||||
% output:
|
||||
% newdata: the covnerted data if the input data does contain a JData
|
||||
% structure; otherwise, the same as the input.
|
||||
%
|
||||
% examples:
|
||||
% obj=struct('_ArrayType_','double','_ArraySize_',[2 3],
|
||||
% '_ArrayIsSparse_',1 ,'_ArrayData_',null);
|
||||
% ubjdata=struct2jdata(obj);
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
fn=fieldnames(data);
|
||||
newdata=data;
|
||||
len=length(data);
|
||||
needbase64=jsonopt('Base64',1,varargin{:});
|
||||
if(jsonopt('Recursive',0,varargin{:})==1)
|
||||
for i=1:length(fn) % depth-first
|
||||
for j=1:len
|
||||
if(isstruct(getfield(data(j),fn{i})))
|
||||
newdata(j)=setfield(newdata(j),fn{i},jstruct2array(getfield(data(j),fn{i})));
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if(~isempty(strmatch('x0x5F_ArrayType_',fn)) && (~isempty(strmatch('x0x5F_ArrayData_',fn)) || ~isempty(strmatch('x0x5F_ArrayCompressedData_',fn))))
|
||||
newdata=cell(len,1);
|
||||
for j=1:len
|
||||
if(~isempty(strmatch('x0x5F_ArrayCompressionSize_',fn)) && ~isempty(strmatch('x0x5F_ArrayCompressedData_',fn)))
|
||||
zipmethod='zip';
|
||||
if(~isempty(strmatch('x0x5F_ArrayCompressionMethod_',fn)))
|
||||
zipmethod=data(j).x0x5F_ArrayCompressionMethod_;
|
||||
end
|
||||
if(strcmpi(zipmethod,'gzip'))
|
||||
if(needbase64)
|
||||
ndata=reshape(typecast(gzipdecode(base64decode(data(j).x0x5F_ArrayCompressedData_)),data(j).x0x5F_ArrayType_),data(j).x0x5F_ArrayCompressionSize_);
|
||||
else
|
||||
ndata=reshape(typecast(gzipdecode(data(j).x0x5F_ArrayCompressedData_),data(j).x0x5F_ArrayType_),data(j).x0x5F_ArrayCompressionSize_);
|
||||
end
|
||||
elseif(strcmpi(zipmethod,'zlib'))
|
||||
if(needbase64)
|
||||
ndata=reshape(typecast(zlibdecode(base64decode(data(j).x0x5F_ArrayCompressedData_)),data(j).x0x5F_ArrayType_),data(j).x0x5F_ArrayCompressionSize_);
|
||||
else
|
||||
ndata=reshape(typecast(zlibdecode(data(j).x0x5F_ArrayCompressedData_),data(j).x0x5F_ArrayType_),data(j).x0x5F_ArrayCompressionSize_);
|
||||
end
|
||||
else
|
||||
error('compression method is not supported');
|
||||
end
|
||||
else
|
||||
ndata=cast(data(j).x0x5F_ArrayData_,data(j).x0x5F_ArrayType_);
|
||||
end
|
||||
iscpx=0;
|
||||
if(~isempty(strmatch('x0x5F_ArrayIsComplex_',fn)))
|
||||
if(data(j).x0x5F_ArrayIsComplex_)
|
||||
iscpx=1;
|
||||
end
|
||||
end
|
||||
if(~isempty(strmatch('x0x5F_ArrayIsSparse_',fn)))
|
||||
if(data(j).x0x5F_ArrayIsSparse_)
|
||||
if(~isempty(strmatch('x0x5F_ArraySize_',fn)))
|
||||
dim=double(data(j).x0x5F_ArraySize_);
|
||||
if(iscpx && size(ndata,2)==4-any(dim==1))
|
||||
ndata(:,end-1)=complex(ndata(:,end-1),ndata(:,end));
|
||||
end
|
||||
if isempty(ndata)
|
||||
% All-zeros sparse
|
||||
ndata=sparse(dim(1),prod(dim(2:end)));
|
||||
elseif dim(1)==1
|
||||
% Sparse row vector
|
||||
ndata=sparse(1,ndata(:,1),ndata(:,2),dim(1),prod(dim(2:end)));
|
||||
elseif dim(2)==1
|
||||
% Sparse column vector
|
||||
ndata=sparse(ndata(:,1),1,ndata(:,2),dim(1),prod(dim(2:end)));
|
||||
else
|
||||
% Generic sparse array.
|
||||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3),dim(1),prod(dim(2:end)));
|
||||
end
|
||||
else
|
||||
if(iscpx && size(ndata,2)==4)
|
||||
ndata(:,3)=complex(ndata(:,3),ndata(:,4));
|
||||
end
|
||||
ndata=sparse(ndata(:,1),ndata(:,2),ndata(:,3));
|
||||
end
|
||||
end
|
||||
elseif(~isempty(strmatch('x0x5F_ArraySize_',fn)))
|
||||
if(iscpx && size(ndata,2)==2)
|
||||
ndata=complex(ndata(:,1),ndata(:,2));
|
||||
end
|
||||
ndata=reshape(ndata(:),data(j).x0x5F_ArraySize_);
|
||||
end
|
||||
newdata{j}=ndata;
|
||||
end
|
||||
if(len==1)
|
||||
newdata=newdata{1};
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
function opt=varargin2struct(varargin)
|
||||
import jsonlab.*
|
||||
%
|
||||
% opt=varargin2struct('param1',value1,'param2',value2,...)
|
||||
% or
|
||||
% opt=varargin2struct(...,optstruct,...)
|
||||
%
|
||||
% convert a series of input parameters into a structure
|
||||
%
|
||||
% authors:Qianqian Fang (q.fang <at> neu.edu)
|
||||
% date: 2012/12/22
|
||||
%
|
||||
% input:
|
||||
% 'param', value: the input parameters should be pairs of a string and a value
|
||||
% optstruct: if a parameter is a struct, the fields will be merged to the output struct
|
||||
%
|
||||
% output:
|
||||
% opt: a struct where opt.param1=value1, opt.param2=value2 ...
|
||||
%
|
||||
% license:
|
||||
% BSD, see LICENSE_BSD.txt file for details
|
||||
%
|
||||
% -- this function is part of jsonlab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
|
||||
%
|
||||
|
||||
len=length(varargin);
|
||||
opt=struct;
|
||||
if(len==0) return; end
|
||||
i=1;
|
||||
while(i<=len)
|
||||
if(isstruct(varargin{i}))
|
||||
opt=mergestruct(opt,varargin{i});
|
||||
elseif(ischar(varargin{i}) && i<len)
|
||||
opt=setfield(opt,lower(varargin{i}),varargin{i+1});
|
||||
i=i+1;
|
||||
else
|
||||
error('input must be in the form of ...,''name'',value,... pairs or structs');
|
||||
end
|
||||
i=i+1;
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
function output = zlibdecode(input)
|
||||
import jsonlab.*
|
||||
%ZLIBDECODE Decompress input bytes using ZLIB.
|
||||
%
|
||||
% output = zlibdecode(input)
|
||||
%
|
||||
% The function takes a compressed byte array INPUT and returns inflated
|
||||
% bytes OUTPUT. The INPUT is a result of GZIPENCODE function. The OUTPUT
|
||||
% is always an 1-by-N uint8 array. JAVA must be enabled to use the function.
|
||||
%
|
||||
% See also zlibencode typecast
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(uint8(input),0,'zlib');
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input)
|
||||
warning('zlibdecode:inputTypeMismatch', ...
|
||||
'Input is char, but treated as uint8.');
|
||||
input = uint8(input);
|
||||
end
|
||||
if ~isa(input, 'int8') && ~isa(input, 'uint8')
|
||||
error('Input must be either int8 or uint8.');
|
||||
end
|
||||
|
||||
buffer = java.io.ByteArrayOutputStream();
|
||||
zlib = java.util.zip.InflaterOutputStream(buffer);
|
||||
zlib.write(input, 0, numel(input));
|
||||
zlib.close();
|
||||
output = typecast(buffer.toByteArray(), 'uint8')';
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
function output = zlibencode(input)
|
||||
import jsonlab.*
|
||||
%ZLIBENCODE Compress input bytes with ZLIB.
|
||||
%
|
||||
% output = zlibencode(input)
|
||||
%
|
||||
% The function takes a char, int8, or uint8 array INPUT and returns
|
||||
% compressed bytes OUTPUT as a uint8 array. Note that the compression
|
||||
% doesn't preserve input dimensions. JAVA must be enabled to use the
|
||||
% function.
|
||||
%
|
||||
% See also zlibdecode typecast
|
||||
%
|
||||
% Copyright (c) 2012, Kota Yamaguchi
|
||||
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
|
||||
% License : BSD, see LICENSE_*.txt
|
||||
%
|
||||
|
||||
|
||||
if(nargin==0)
|
||||
error('you must provide at least 1 input');
|
||||
end
|
||||
if(exist('zmat')==3)
|
||||
output=zmat(input,1,'zlib');
|
||||
return;
|
||||
end
|
||||
error(javachk('jvm'));
|
||||
if ischar(input), input = uint8(input); end
|
||||
if ~isa(input, 'int8') && ~isa(input, 'uint8')
|
||||
error('Input must be either char, int8 or uint8.');
|
||||
end
|
||||
|
||||
buffer = java.io.ByteArrayOutputStream();
|
||||
zlib = java.util.zip.DeflaterOutputStream(buffer);
|
||||
zlib.write(input, 0, numel(input));
|
||||
zlib.close();
|
||||
output = typecast(buffer.toByteArray(), 'uint8')';
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
# A MessagePack implementation for Matlab and Octave
|
||||
|
||||
The code is written in pure Matlab, and has no dependencies beyond Matlab itself. And it works in recent versions of Octave, too.
|
||||
|
||||
The files in this repository are taken from [Transplant](https://github.com/bastibe/transplant).
|
||||
|
||||
## Basic Usage:
|
||||
```matlab
|
||||
data = {'life, the universe, and everything', struct('the_answer', 42)};
|
||||
bytes = dumpmsgpack(data)
|
||||
data = parsemsgpack(bytes)
|
||||
% returns: {'life, the universe, and everything', containers.Map('the_answer', 42)}
|
||||
```
|
||||
|
||||
## Converting Matlab to MsgPack:
|
||||
|
||||
| Matlab | MsgPack |
|
||||
| -------------- | ------------------------- |
|
||||
| string | string |
|
||||
| scalar | number |
|
||||
| logical | `true`/`false` |
|
||||
| vector | array of numbers |
|
||||
| uint8 vector | bin |
|
||||
| matrix | array of array of numbers |
|
||||
| empty matrix | nil |
|
||||
| cell array | array |
|
||||
| cell matrix | array of arrays |
|
||||
| struct | map |
|
||||
| containers.Map | map |
|
||||
| struct array | array of maps |
|
||||
| handles | raise error |
|
||||
|
||||
There is no way of encoding exts
|
||||
|
||||
## Converting MsgPack to Matlab
|
||||
|
||||
| MsgPack | Matlab |
|
||||
| -------------- | -------------- |
|
||||
| string | string |
|
||||
| number | scalar |
|
||||
| `true`/`false` | logical |
|
||||
| nil | empty matrix |
|
||||
| array | cell array |
|
||||
| map | containers.Map |
|
||||
| bin | uint8 |
|
||||
| ext | uint8 |
|
||||
|
||||
Note that since `structs` don't support arbitrary field names, they can't be used for representing `maps`. We use `containers.Map` instead.
|
||||
|
||||
## Tests
|
||||
```matlab
|
||||
runtests()
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MATLAB (R) is copyright of the Mathworks
|
||||
|
||||
Copyright (c) 2014 Bastian Bechtold
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
%DUMPMSGPACK dumps Matlab data structures as a msgpack data
|
||||
% DUMPMSGPACK(DATA)
|
||||
% recursively walks through DATA and creates a msgpack byte buffer from it.
|
||||
% - strings are converted to strings
|
||||
% - scalars are converted to numbers
|
||||
% - logicals are converted to `true` and `false`
|
||||
% - arrays are converted to arrays of numbers
|
||||
% - matrices are converted to arrays of arrays of numbers
|
||||
% - empty matrices are converted to nil
|
||||
% - cell arrays are converted to arrays
|
||||
% - cell matrices are converted to arrays of arrays
|
||||
% - struct arrays are converted to arrays of maps
|
||||
% - structs and container.Maps are converted to maps
|
||||
% - function handles and matlab objects will raise an error.
|
||||
%
|
||||
% There is no way of encoding bins or exts
|
||||
|
||||
% (c) 2016 Bastian Bechtold
|
||||
% This code is licensed under the BSD 3-clause license
|
||||
|
||||
function msgpack = dumpmsgpack(data)
|
||||
msgpack = dump(data);
|
||||
% collect all parts in a cell array to avoid frequent uint8
|
||||
% concatenations.
|
||||
msgpack = [msgpack{:}];
|
||||
end
|
||||
|
||||
function msgpack = dump(data)
|
||||
% convert numeric matrices to cell matrices since msgpack doesn't know matrices
|
||||
if (isnumeric(data) || islogical(data)) && ...
|
||||
~(isvector(data) && isa(data, 'uint8')) && ~isscalar(data) && ~isempty(data)
|
||||
data = num2cell(data);
|
||||
end
|
||||
% convert character matrices to cell of strings or cell matrices
|
||||
if ischar(data) && ~(isvector(data)||isempty(data)) && ndims(data) == 2
|
||||
data = cellstr(data);
|
||||
elseif ischar(data) && ~isvector(data)
|
||||
data = num2cell(data);
|
||||
end
|
||||
% convert struct arrays to cell of structs
|
||||
if isstruct(data) && ~isscalar(data)
|
||||
data = num2cell(data);
|
||||
end
|
||||
% standardize on always using maps instead of structs
|
||||
if isstruct(data)
|
||||
if ~isempty(fieldnames(data))
|
||||
data = containers.Map(fieldnames(data), struct2cell(data));
|
||||
else
|
||||
data = containers.Map();
|
||||
end
|
||||
end
|
||||
|
||||
if isnumeric(data) && isempty(data)
|
||||
msgpack = {uint8(192)}; % encode nil
|
||||
elseif isa(data, 'uint8') && numel(data) > 1
|
||||
msgpack = dumpbin(data);
|
||||
elseif islogical(data)
|
||||
if data
|
||||
msgpack = {uint8(195)}; % encode true
|
||||
else
|
||||
msgpack = {uint8(194)}; % encode false
|
||||
end
|
||||
elseif isinteger(data)
|
||||
msgpack = {dumpinteger(data)};
|
||||
elseif isnumeric(data)
|
||||
msgpack = {dumpfloat(data)};
|
||||
elseif ischar(data)
|
||||
msgpack = dumpstring(data);
|
||||
elseif iscell(data)
|
||||
msgpack = dumpcell(data);
|
||||
elseif isa(data, 'containers.Map')
|
||||
msgpack = dumpmap(data);
|
||||
else
|
||||
error('transplant:dumpmsgpack:unknowntype', ...
|
||||
['Unknown type "' class(data) '"']);
|
||||
end
|
||||
end
|
||||
|
||||
function bytes = scalar2bytes(value)
|
||||
% reverse byte order to convert from little endian to big endian
|
||||
bytes = typecast(swapbytes(value), 'uint8');
|
||||
end
|
||||
|
||||
function msgpack = dumpinteger(value)
|
||||
% if the values are small enough, encode as fixnum:
|
||||
if value >= 0 && value < 128
|
||||
% first bit is 0, last 7 bits are value
|
||||
msgpack = uint8(value);
|
||||
return
|
||||
elseif value < 0 && value > -32
|
||||
% first three bits are 111, last 5 bytes are value
|
||||
msgpack = typecast(int8(value), 'uint8');
|
||||
return
|
||||
end
|
||||
|
||||
% otherwise, encode by type:
|
||||
switch class(value)
|
||||
case 'uint8' % encode as uint8
|
||||
msgpack = uint8([204, value]);
|
||||
case 'uint16' % encode as uint16
|
||||
msgpack = uint8([205, scalar2bytes(value)]);
|
||||
case 'uint32' % encode as uint32
|
||||
msgpack = uint8([206, scalar2bytes(value)]);
|
||||
case 'uint64' % encode as uint64
|
||||
msgpack = uint8([207, scalar2bytes(value)]);
|
||||
case 'int8' % encode as int8
|
||||
msgpack = uint8([208, scalar2bytes(value)]);
|
||||
case 'int16' % encode as int16
|
||||
msgpack = uint8([209, scalar2bytes(value)]);
|
||||
case 'int32' % encode as int32
|
||||
msgpack = uint8([210, scalar2bytes(value)]);
|
||||
case 'int64' % encode as int64
|
||||
msgpack = uint8([211, scalar2bytes(value)]);
|
||||
otherwise
|
||||
error('transplant:dumpmsgpack:unknowninteger', ...
|
||||
['Unknown integer type "' class(value) '"']);
|
||||
end
|
||||
end
|
||||
|
||||
function msgpack = dumpfloat(value)
|
||||
% do double first, as it is more common in Matlab
|
||||
if isa(value, 'double') % encode as float64
|
||||
msgpack = uint8([203, scalar2bytes(value)]);
|
||||
elseif isa(value, 'single') % encode as float32
|
||||
msgpack = uint8([202, scalar2bytes(value)]);
|
||||
else
|
||||
error('transplant:dumpmsgpack:unknownfloat', ...
|
||||
['Unknown float type "' class(value) '"']);
|
||||
end
|
||||
end
|
||||
|
||||
function msgpack = dumpstring(value)
|
||||
b10100000 = 160;
|
||||
|
||||
encoded = unicode2native(value, 'utf-8');
|
||||
len = length(encoded);
|
||||
|
||||
if len < 32 % encode as fixint:
|
||||
% first three bits are 101, last 5 are length:
|
||||
msgpack = {uint8(bitor(len, b10100000)), encoded};
|
||||
elseif len < 256 % encode as str8
|
||||
msgpack = {uint8([217, len]), encoded};
|
||||
elseif len < 2^16 % encode as str16
|
||||
msgpack = {uint8(218), scalar2bytes(uint16(len)), encoded};
|
||||
elseif len < 2^32 % encode as str32
|
||||
msgpack = {uint8(219), scalar2bytes(uint32(len)), encoded};
|
||||
else
|
||||
error('transplant:dumpmsgpack:stringtoolong', ...
|
||||
sprintf('String is too long (%d bytes)', len));
|
||||
end
|
||||
end
|
||||
|
||||
function msgpack = dumpbin(value)
|
||||
len = length(value);
|
||||
if len < 256 % encode as bin8
|
||||
msgpack = {uint8([196, len]) value(:)'};
|
||||
elseif len < 2^16 % encode as bin16
|
||||
msgpack = {uint8(197), scalar2bytes(uint16(len)), value(:)'};
|
||||
elseif len < 2^32 % encode as bin32
|
||||
msgpack = {uint8(198), scalar2bytes(uint32(len)), value(:)'};
|
||||
else
|
||||
error('transplant:dumpmsgpack:bintoolong', ...
|
||||
sprintf('Bin is too long (%d bytes)', len));
|
||||
end
|
||||
end
|
||||
|
||||
function msgpack = dumpcell(value)
|
||||
b10010000 = 144;
|
||||
|
||||
% Msgpack can only work with 1D-arrays. Thus, Convert a
|
||||
% multidimensional AxBxC array into a cell-of-cell-of-cell, so
|
||||
% that indexing value{a, b, c} becomes value{a}{b}{c}.
|
||||
if length(value) ~= prod(size(value))
|
||||
for n=ndims(value):-1:2
|
||||
value = cellfun(@squeeze, num2cell(value, n), ...
|
||||
'uniformoutput', false);
|
||||
end
|
||||
end
|
||||
|
||||
% write header
|
||||
len = length(value);
|
||||
if len < 16 % encode as fixarray
|
||||
% first four bits are 1001, last 4 are length
|
||||
msgpack = {uint8(bitor(len, b10010000))};
|
||||
elseif len < 2^16 % encode as array16
|
||||
msgpack = {uint8(220), scalar2bytes(uint16(len))};
|
||||
elseif len < 2^32 % encode as array32
|
||||
msgpack = {uint8(221), scalar2bytes(uint32(len))};
|
||||
else
|
||||
error('transplant:dumpmsgpack:arraytoolong', ...
|
||||
sprintf('Array is too long (%d elements)', len));
|
||||
end
|
||||
|
||||
% write values
|
||||
for n=1:len
|
||||
stuff = dump(value{n});
|
||||
msgpack = [msgpack stuff{:}];
|
||||
end
|
||||
end
|
||||
|
||||
function msgpack = dumpmap(value)
|
||||
b10000000 = 128;
|
||||
|
||||
% write header
|
||||
len = length(value);
|
||||
if len < 16 % encode as fixmap
|
||||
% first four bits are 1000, last 4 are length
|
||||
msgpack = {uint8(bitor(len, b10000000))};
|
||||
elseif len < 2^16 % encode as map16
|
||||
msgpack = {uint8(222), scalar2bytes(uint16(len))};
|
||||
elseif len < 2^32 % encode as map32
|
||||
msgpack = {uint8(223), scalar2bytes(uint32(len))};
|
||||
else
|
||||
error('transplant:dumpmsgpack:maptoolong', ...
|
||||
sprintf('Map is too long (%d elements)', len));
|
||||
end
|
||||
|
||||
% write key-value pairs
|
||||
keys = value.keys();
|
||||
values = value.values();
|
||||
for n=1:len
|
||||
keystuff = dump(keys{n});
|
||||
valuestuff = dump(values{n});
|
||||
msgpack = [msgpack, keystuff{:}, valuestuff{:}];
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
%% positive integer dumping
|
||||
if dumpmsgpack(int8(0)) ~= uint8(0)
|
||||
error('Dumping 0 failed')
|
||||
end
|
||||
if any(dumpmsgpack(uint8(1)) ~= uint8(1))
|
||||
error('Dumping positive fixnum failed')
|
||||
end
|
||||
if any(dumpmsgpack(uint8(128)) ~= uint8([204, 128]))
|
||||
error('Dumping uint8 failed')
|
||||
end
|
||||
if any(dumpmsgpack(uint16(256)) ~= uint8([205, 1, 0]))
|
||||
error('Dumping uint16 failed')
|
||||
end
|
||||
if any(dumpmsgpack(uint32(2^16)) ~= uint8([206, 0, 1, 0, 0]))
|
||||
error('Dumping uint32 failed')
|
||||
end
|
||||
if any(dumpmsgpack(uint64(2^32)) ~= uint8([207, 0, 0, 0, 1, 0, 0, 0, 0]))
|
||||
error('Dumping uint64 failed')
|
||||
end
|
||||
|
||||
%% negative integer dumping
|
||||
if dumpmsgpack(int8(-1)) ~= uint8(255)
|
||||
error('Dumping negative fixnum failed')
|
||||
end
|
||||
if any(dumpmsgpack(int8(-128)) ~= uint8([208, 128]))
|
||||
error('Dumping int8 failed')
|
||||
end
|
||||
if any(dumpmsgpack(int16(-256)) ~= uint8([209, 255, 0]))
|
||||
error('Dumping int16 failed')
|
||||
end
|
||||
if any(dumpmsgpack(int32(-2^16)) ~= uint8([210, 255, 255, 0, 0]))
|
||||
error('Dumping int32 failed')
|
||||
end
|
||||
if any(dumpmsgpack(int64(-2^32)) ~= uint8([211, 255, 255, 255, 255, 0, 0, 0, 0]))
|
||||
error('Dumping int64 failed')
|
||||
end
|
||||
|
||||
%% float dumping
|
||||
if any(dumpmsgpack(single(1.5)) ~= uint8([202, 63, 192, 0, 0]))
|
||||
error('Dumping float32 failed')
|
||||
end
|
||||
if any(dumpmsgpack(double(1.5)) ~= uint8([203, 63, 248, 0, 0, 0, 0, 0, 0]))
|
||||
error('Dumping float64 failed')
|
||||
end
|
||||
|
||||
%% string dumping
|
||||
if any(dumpmsgpack('foo') ~= uint8([163, 102, 111, 111]))
|
||||
error('Dumping fixstr failed')
|
||||
end
|
||||
if any(dumpmsgpack(repmat('a', [1, 32])) ~= uint8([217, 32, ones(1, 32)*'a']))
|
||||
error('Dumping str8 failed')
|
||||
end
|
||||
if any(dumpmsgpack(repmat('a', [1, 2^8])) ~= uint8([218, 1, 0, ones(1, 2^8)*'a']))
|
||||
error('Dumping str16 failed')
|
||||
end
|
||||
if any(dumpmsgpack(repmat('a', [1, 2^16])) ~= uint8([219, 0, 1, 0, 0, ones(1, 2^16)*'a']))
|
||||
error('Dumping str16 failed')
|
||||
end
|
||||
|
||||
%% bin dumping
|
||||
if any(dumpmsgpack(repmat(uint8(42), [1, 32])) ~= uint8([196, 32, ones(1, 32)*42]))
|
||||
error('Dumping str8 failed')
|
||||
end
|
||||
if any(dumpmsgpack(repmat(uint8(42), [1, 2^8])) ~= uint8([197, 1, 0, ones(1, 2^8)*42]))
|
||||
error('Dumping str16 failed')
|
||||
end
|
||||
if any(dumpmsgpack(repmat(uint8(42), [1, 2^16])) ~= uint8([198, 0, 1, 0, 0, ones(1, 2^16)*42]))
|
||||
error('Dumping str16 failed')
|
||||
end
|
||||
|
||||
%% array dumping
|
||||
if any(dumpmsgpack({uint8(1), uint8(2)}) ~= uint8([146, 1, 2]))
|
||||
error('Dumping fixarray failed')
|
||||
end
|
||||
if any(dumpmsgpack(num2cell(repmat(uint8(42), [1, 16]))) ~= uint8([220, 0, 16, repmat(42, [1, 16])]))
|
||||
error('Dumping array16 failed')
|
||||
end
|
||||
% takes too long:
|
||||
% if any(dumpmsgpack(num2cell(repmat(uint8(42), [1, 2^16]))) ~= uint8([221, 0, 1, 0, 0 repmat(42, [1, 2^16])]))
|
||||
% error('Dumping array32 failed')
|
||||
% end
|
||||
|
||||
%% map dumping
|
||||
if any(dumpmsgpack(struct('one', uint8(1), 'two', uint8(2))) ~= uint8([130, dumpmsgpack('one'), 1, dumpmsgpack('two'), 2]))
|
||||
error('Dumping fixmap failed')
|
||||
end
|
||||
data = struct();
|
||||
msgpack = uint8([]);
|
||||
for n=[1 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9] % default struct field order
|
||||
data.(['x' num2str(n)]) = uint8(n);
|
||||
msgpack = [msgpack dumpmsgpack(['x' num2str(n)]) uint8(n)];
|
||||
end
|
||||
if any(dumpmsgpack(data) ~= uint8([222, 0, 16, msgpack]))
|
||||
error('Dumping map16 failed')
|
||||
end
|
||||
% map32 takes too long
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
%PARSEMSGPACK parses a msgpack byte buffer into Matlab data structures
|
||||
% PARSEMSGPACK(BYTES)
|
||||
% reads BYTES as msgpack data, and creates Matlab data structures
|
||||
% from it. The number of bytes consumed by the parsemsgpack call
|
||||
% is returned in the variable IDX.
|
||||
% - strings are converted to strings
|
||||
% - numbers are converted to appropriate numeric values
|
||||
% - true, false are converted to logical 1, 0
|
||||
% - nil is converted to []
|
||||
% - arrays are converted to cell arrays
|
||||
% - maps are converted to containers.Map
|
||||
|
||||
% (c) 2016 Bastian Bechtold
|
||||
% This code is licensed under the BSD 3-clause license
|
||||
|
||||
function [obj, idx] = parsemsgpack(bytes)
|
||||
[obj, idx] = parse(uint8(bytes(:)), 1);
|
||||
end
|
||||
|
||||
function [obj, idx] = parse(bytes, idx)
|
||||
% masks:
|
||||
b10000000 = 128;
|
||||
b01111111 = 127;
|
||||
b11000000 = 192;
|
||||
b00111111 = 63;
|
||||
b11100000 = 224;
|
||||
b00011111 = 31;
|
||||
b11110000 = 240;
|
||||
b00001111 = 15;
|
||||
% values:
|
||||
b00000000 = 0;
|
||||
b10010000 = 144;
|
||||
b10100000 = 160;
|
||||
|
||||
currentbyte = bytes(idx);
|
||||
|
||||
if bitand(b10000000, currentbyte) == b00000000
|
||||
% decode positive fixint
|
||||
obj = int8(currentbyte);
|
||||
idx = idx + 1;
|
||||
return
|
||||
elseif bitand(b11100000, currentbyte) == b11100000
|
||||
% decode negative fixint
|
||||
obj = typecast(currentbyte, 'int8');
|
||||
idx = idx + 1;
|
||||
return
|
||||
elseif bitand(b11110000, currentbyte) == b10000000
|
||||
% decode fixmap
|
||||
len = double(bitand(b00001111, currentbyte));
|
||||
[obj, idx] = parsemap(len, bytes, idx+1);
|
||||
return
|
||||
elseif bitand(b11110000, currentbyte) == b10010000
|
||||
% decode fixarray
|
||||
len = double(bitand(b00001111, currentbyte));
|
||||
[obj, idx] = parsearray(len, bytes, idx+1);
|
||||
return
|
||||
elseif bitand(b11100000, currentbyte) == b10100000
|
||||
% decode fixstr
|
||||
len = double(bitand(b00011111, currentbyte));
|
||||
[obj, idx] = parsestring(len, bytes, idx + 1);
|
||||
return
|
||||
end
|
||||
|
||||
switch currentbyte
|
||||
case 192 % nil
|
||||
obj = [];
|
||||
idx = idx+1;
|
||||
% case 193 % unused
|
||||
case 194 % false
|
||||
obj = false;
|
||||
idx = idx+1;
|
||||
case 195 % true
|
||||
obj = true;
|
||||
idx = idx+1;
|
||||
case 196 % bin8
|
||||
len = double(bytes(idx+1));
|
||||
[obj, idx] = parsebytes(len, bytes, idx+2);
|
||||
case 197 % bin16
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
|
||||
[obj, idx] = parsebytes(len, bytes, idx+3);
|
||||
case 198 % bin32
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
|
||||
[obj, idx] = parsebytes(len, bytes, idx+5);
|
||||
case 199 % ext8
|
||||
len = double(bytes(idx+1));
|
||||
[obj, idx] = parseext(len, bytes, idx+2);
|
||||
case 200 % ext16
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
|
||||
[obj, idx] = parseext(len, bytes, idx+3);
|
||||
case 201 % ext32
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
|
||||
[obj, idx] = parseext(len, bytes, idx+5);
|
||||
case 202 % float32
|
||||
obj = bytes2scalar(bytes(idx+1:idx+4), 'single');
|
||||
idx = idx+5;
|
||||
case 203 % float64
|
||||
obj = bytes2scalar(bytes(idx+1:idx+8), 'double');
|
||||
idx = idx+9;
|
||||
case 204 % uint8
|
||||
obj = bytes(idx+1);
|
||||
idx = idx+2;
|
||||
case 205 % uint16
|
||||
obj = bytes2scalar(bytes(idx+1:idx+2), 'uint16');
|
||||
idx = idx+3;
|
||||
case 206 % uint32
|
||||
obj = bytes2scalar(bytes(idx+1:idx+4), 'uint32');
|
||||
idx = idx+5;
|
||||
case 207 % uint64
|
||||
obj = bytes2scalar(bytes(idx+1:idx+8), 'uint64');
|
||||
idx = idx+9;
|
||||
case 208 % int8
|
||||
obj = bytes2scalar(bytes(idx+1), 'int8');
|
||||
idx = idx+2;
|
||||
case 209 % int16
|
||||
obj = bytes2scalar(bytes(idx+1:idx+2), 'int16');
|
||||
idx = idx+3;
|
||||
case 210 % int32
|
||||
obj = bytes2scalar(bytes(idx+1:idx+4), 'int32');
|
||||
idx = idx+5;
|
||||
case 211 % int64
|
||||
obj = bytes2scalar(bytes(idx+1:idx+8), 'int64');
|
||||
idx = idx+9;
|
||||
case 212 % fixext1
|
||||
[obj, idx] = parseext(1, bytes, idx+1);
|
||||
case 213 % fixext2
|
||||
[obj, idx] = parseext(2, bytes, idx+1);
|
||||
case 214 % fixext4
|
||||
[obj, idx] = parseext(4, bytes, idx+1);
|
||||
case 215 % fixext8
|
||||
[obj, idx] = parseext(8, bytes, idx+1);
|
||||
case 216 % fixext16
|
||||
[obj, idx] = parseext(16, bytes, idx+1);
|
||||
case 217 % str8
|
||||
len = double(bytes(idx+1));
|
||||
[obj, idx] = parsestring(len, bytes, idx+2);
|
||||
case 218 % str16
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
|
||||
[obj, idx] = parsestring(len, bytes, idx+3);
|
||||
case 219 % str32
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
|
||||
[obj, idx] = parsestring(len, bytes, idx+5);
|
||||
case 220 % array16
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
|
||||
[obj, idx] = parsearray(len, bytes, idx+3);
|
||||
case 221 % array32
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
|
||||
[obj, idx] = parsearray(len, bytes, idx+5);
|
||||
case 222 % map16
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
|
||||
[obj, idx] = parsemap(len, bytes, idx+3);
|
||||
case 223 % map32
|
||||
len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
|
||||
[obj, idx] = parsemap(len, bytes, idx+5);
|
||||
otherwise
|
||||
error('transplant:parsemsgpack:unknowntype', ...
|
||||
['Unknown type "' dec2bin(currentbyte) '"']);
|
||||
end
|
||||
end
|
||||
|
||||
function value = bytes2scalar(bytes, type)
|
||||
% reverse byte order to convert from little-endian to big-endian
|
||||
value = typecast(bytes(end:-1:1), type);
|
||||
end
|
||||
|
||||
function [str, idx] = parsestring(len, bytes, idx)
|
||||
str = native2unicode(bytes(idx:idx+len-1)', 'utf-8');
|
||||
idx = idx + len;
|
||||
end
|
||||
|
||||
function [out, idx] = parsebytes(len, bytes, idx)
|
||||
out = bytes(idx:idx+len-1);
|
||||
idx = idx + len;
|
||||
end
|
||||
|
||||
function [out, idx] = parseext(len, bytes, idx)
|
||||
out.type = bytes(idx);
|
||||
out.data = bytes(idx+1:idx+len);
|
||||
idx = idx + len + 1;
|
||||
end
|
||||
|
||||
function [out, idx] = parsearray(len, bytes, idx)
|
||||
out = cell(1, len);
|
||||
for n=1:len
|
||||
[out{n}, idx] = parse(bytes, idx);
|
||||
end
|
||||
end
|
||||
|
||||
function [out, idx] = parsemap(len, bytes, idx)
|
||||
out = containers.Map();
|
||||
for n=1:len
|
||||
[key, idx] = parse(bytes, idx);
|
||||
[out(key), idx] = parse(bytes, idx);
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
%% positive integer parsing
|
||||
if parsemsgpack(uint8(0)) ~= uint8(0)
|
||||
error('Parsing 0 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8(1)) ~= uint8(1))
|
||||
error('Parsing positive fixnum failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([204, 128])) ~= uint8(128))
|
||||
error('Parsing uint8 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([205, 1, 0])) ~= uint16(256))
|
||||
error('Parsing uint16 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([206, 0, 1, 0, 0])) ~= uint32(2^16))
|
||||
error('Parsing uint32 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([207, 0, 0, 0, 1, 0, 0, 0, 0])) ~= uint64(2^32))
|
||||
error('Parsing uint64 failed')
|
||||
end
|
||||
|
||||
%% negative integer parsing
|
||||
if any(parsemsgpack(uint8(255)) ~= int8(-1))
|
||||
error('Parsing negative fixnum failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([208, 128])) ~= int8(-128))
|
||||
error('Parsing int8 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([209, 255, 0])) ~= int16(-256))
|
||||
error('Parsing int16 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([210, 255, 255, 0, 0])) ~= int32(-2^16))
|
||||
error('Parsing int32 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([211, 255, 255, 255, 255, 0, 0, 0, 0])) ~= int64(-2^32))
|
||||
error('Parsing int64 failed')
|
||||
end
|
||||
|
||||
%% float parsing
|
||||
if any(parsemsgpack(uint8([202, 63, 192, 0, 0])) ~= single(1.5))
|
||||
error('Parsing float32 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([203, 63, 248, 0, 0, 0, 0, 0, 0])) ~= double(1.5))
|
||||
error('Parsing float64 failed')
|
||||
end
|
||||
|
||||
%% string parsing
|
||||
if any(parsemsgpack(uint8([163, 102, 111, 111])) ~= 'foo')
|
||||
error('Parsing fixstr failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([217, 32, ones(1, 32)*'a'])) ~= repmat('a', [1, 32]))
|
||||
error('Parsing str8 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([218, 1, 0, ones(1, 2^8)*'a'])) ~= repmat('a', [1, 2^8]))
|
||||
error('Parsing str16 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([219, 0, 1, 0, 0, ones(1, 2^16)*'a'])) ~= repmat('a', [1, 2^16]))
|
||||
error('Parsing str16 failed')
|
||||
end
|
||||
|
||||
%% bin parsing
|
||||
if any(parsemsgpack(uint8([196, 32, ones(1, 32)*42])) ~= repmat(uint8(42), [1, 32]))
|
||||
error('Parsing str8 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([197, 1, 0, ones(1, 2^8)*42])) ~= repmat(uint8(42), [1, 2^8]))
|
||||
error('Parsing str16 failed')
|
||||
end
|
||||
if any(parsemsgpack(uint8([198, 0, 1, 0, 0, ones(1, 2^16)*42])) ~= repmat(uint8(42), [1, 2^16]))
|
||||
error('Parsing str16 failed')
|
||||
end
|
||||
|
||||
%% array parsing
|
||||
c = parsemsgpack(uint8([146, 1, 2]));
|
||||
d = {uint8(1), uint8(2)};
|
||||
for n=1:max([length(c), length(d)])
|
||||
if c{n} ~= d{n}
|
||||
error('Parsing fixarray failed')
|
||||
end
|
||||
end
|
||||
c = parsemsgpack(uint8([220, 0, 16, repmat(42, [1, 16])]));
|
||||
d = num2cell(repmat(uint8(42), [1, 16]));
|
||||
for n=1:max([length(c), length(d)])
|
||||
if c{n} ~= d{n}
|
||||
error('Parsing array16 failed')
|
||||
end
|
||||
end
|
||||
% array32 takes too long
|
||||
|
||||
%% map parsing
|
||||
c = parsemsgpack(uint8([130, dumpmsgpack('one'), 1, dumpmsgpack('two'), 2]));
|
||||
d = struct('one', uint8(1), 'two', uint8(2));
|
||||
f = [fieldnames(d)' c.keys()];
|
||||
for n=1:length(f)
|
||||
if c(f{n}) ~= d.(f{n})
|
||||
error('Parsing fixmap failed')
|
||||
end
|
||||
end
|
||||
data = struct();
|
||||
msgpack = uint8([222, 0, 16]);
|
||||
for n=[1 10 11 12 13 14 15 16 2 3 4 5 6 7 8 9] % default struct field order
|
||||
data.(['x' num2str(n)]) = uint8(n);
|
||||
msgpack = [msgpack dumpmsgpack(['x' num2str(n)]) uint8(n)];
|
||||
end
|
||||
c = parsemsgpack(msgpack);
|
||||
d = data;
|
||||
f = [fieldnames(d)' c.keys()];
|
||||
for n=1:length(f)
|
||||
if c(f{n}) ~= d.(f{n})
|
||||
error('Parsing map16 failed')
|
||||
end
|
||||
end
|
||||
% map32 takes too long
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
classdef ustar < handle
|
||||
% Low-level utilities for UNIX standard tar files.
|
||||
properties (Access = public)
|
||||
File % file name
|
||||
File % tar file name
|
||||
IndexFile % index file name
|
||||
IOMode % file opened in read-only or read-write mode?
|
||||
NumberOfSubfiles % number of subfiles
|
||||
end
|
||||
|
|
@ -65,6 +66,24 @@ classdef ustar < handle
|
|||
obj.scanArchive();
|
||||
obj.resetCurrent();
|
||||
end
|
||||
function openIndexed(obj,tarfile,indexfile)
|
||||
% obj.open(tarfile,indexfile)
|
||||
% Opens a file in read-only mode while using available
|
||||
% indexing data.
|
||||
% Input
|
||||
% tarfile path to TAR file
|
||||
% indexfile path to index file (in json format)
|
||||
obj.File = tarfile;
|
||||
obj.IndexFile = indexfile;
|
||||
obj.IOMode = 'read';
|
||||
obj.ioflag = 'r';
|
||||
obj.fileID = fopen(obj.File,obj.ioflag);
|
||||
if obj.fileID<0
|
||||
error('Unable to open file: %s',obj.File);
|
||||
end
|
||||
obj.scanIndexFile();
|
||||
obj.resetCurrent();
|
||||
end
|
||||
end
|
||||
%% ------------------------------------------------------------------------%%
|
||||
%% PUBLIC METHODS %%
|
||||
|
|
@ -178,6 +197,88 @@ classdef ustar < handle
|
|||
end
|
||||
obj.resetCurrent();
|
||||
end
|
||||
function scanIndexFile(obj)
|
||||
% obj.scanIndexFile()
|
||||
% Reads tar meta-data from index file into class variables.
|
||||
|
||||
% Check encoding of indexing file
|
||||
[~,~,fileExtension] = fileparts(obj.IndexFile);
|
||||
switch fileExtension
|
||||
case '.simplejson'
|
||||
% Open and read file contents (ASCII)
|
||||
indexfileID = fopen(obj.IndexFile,'r');
|
||||
if indexfileID<0
|
||||
error('Unable to open file: %s',obj.IndexFile);
|
||||
end
|
||||
fseek(indexfileID,0,'bof');
|
||||
jsonstr = fread(indexfileID,'char=>char')';
|
||||
fclose(indexfileID);
|
||||
% Parse JSON and reconstruct filenames
|
||||
if ~isempty(which('jsonlab.loadjson'))
|
||||
% User function from matlab central
|
||||
% This function is preferred, since filenames can be
|
||||
% reconstructed safely from parsed JSON (. <=> _0x2E_)
|
||||
json = jsonlab.loadjson(jsonstr);
|
||||
jsonFields = fieldnames(json);
|
||||
tarFileName = strrep(jsonFields,'_0x2E_','.');
|
||||
elseif ~isempty(which('jsondecode'))
|
||||
% Built-in function
|
||||
% Second choice only, since filename might be ambiguous
|
||||
% if it has no extension, but contains underscore. (. => _)
|
||||
json = jsondecode(jsonstr);
|
||||
jsonFields = fieldnames(json);
|
||||
idxtmp = strfind(jsonFields,'_');
|
||||
tarFileName = jsonFields;
|
||||
for ifield=1:length(jsonFields)
|
||||
if ~isempty(idxtmp{ifield})
|
||||
tarFileName{ifield}(idxtmp{ifield}(end)) = '.';
|
||||
end
|
||||
end
|
||||
else % no JSON decoder available
|
||||
error('No JSON decoder available.');
|
||||
end
|
||||
% Extract important fields
|
||||
nsubfile = length(jsonFields);
|
||||
for isub=1:nsubfile
|
||||
tarFileOffset(isub) = json.(jsonFields{isub}).offset;
|
||||
tarFileSize(isub) = json.(jsonFields{isub}).size;
|
||||
end
|
||||
case '.msgpack'
|
||||
% Open and read file contents (binary)
|
||||
indexfileID = fopen(obj.IndexFile,'rb');
|
||||
if indexfileID<0
|
||||
error('Unable to open file: %s',obj.IndexFile);
|
||||
end
|
||||
fseek(indexfileID,0,'bof');
|
||||
msgbytes = fread(indexfileID,'uint8=>uint8');
|
||||
fclose(indexfileID);
|
||||
% Parse msgpack
|
||||
if ~isempty(which('msgpack.parsemsgpack'))
|
||||
msg = msgpack.parsemsgpack(msgbytes);
|
||||
tarFileName = msg.keys;
|
||||
nsubfile = length(tarFileName);
|
||||
tarFileSize = zeros(1,nsubfile);
|
||||
tarFileOffset = zeros(1,nsubfile);
|
||||
for isub=1:nsubfile
|
||||
tmp = msg(tarFileName{isub});
|
||||
tarFileOffset(isub) = double(tmp{1});
|
||||
tarFileSize(isub) = double(tmp{2});
|
||||
end
|
||||
else % no msgpack decoder available
|
||||
error('No msgpack decoder available.');
|
||||
end
|
||||
otherwise
|
||||
error('Unknown file extension of index file: %s',fileExtension);
|
||||
end
|
||||
|
||||
% Order by offset, i.e. file order within tarball and assign
|
||||
% to class variables
|
||||
[~,idxsort] = sort(tarFileOffset);
|
||||
obj.subFile = {tarFileName{idxsort}}';
|
||||
obj.subFileBeg = tarFileOffset(idxsort)';
|
||||
obj.subFileSize = tarFileSize(idxsort)';
|
||||
obj.NumberOfSubfiles = nsubfile;
|
||||
end
|
||||
function readHeader(obj,scanMode)
|
||||
% obj.readHeader(scanMode)
|
||||
% Reads header data of a subfile in tar-ball and stores information
|
||||
|
|
|
|||
Loading…
Reference in New Issue