- Undocumented Matlab - https://undocumentedmatlab.com -

JSON-Matlab integration

Posted By Yair Altman On March 26, 2014 | 18 Comments

I would like to once again welcome guest blogger Mark Mikofski [1]. Mark has written here last year about JGIT-Matlab integration [2] (p.s., in the recently-released R2014a, MathWorks added GIT support to Simulink projects [3], although for some reason not to Matlab projects). Today, Mark discusses how to integrate JSON with Matlab.

What is JSON

It’s often necessary to save objects and arrays to a file, for lots of reasons. In Matlab, you would just save the desired objects in a mat-file, but that’s a binary format that in general only Matlab can read. One reason you might want to cache objects is to pass to a non-Matlab API. True there are libraries to import mat-files (for example: JMatIO [4]), but there are already accepted standards for passing objects such as XML and JSON (JavaScript Object Notation, http://json.org [5]) that most APIs readily understand. Both of these methods attempt to serialize data into a text based format that limits the types of objects they can contain. Because sometimes the API is a human being who needs to read and edit the file, one of the JSON’s goals is to be “easy for humans to read and write”.
Here’s a sample of a JSON object:

{
    "students": ["Dick", "Jane"],
    "assignments": ["essay", "term paper"]
    "scores": {
        "essay": {"Dick": 86, "Jane": 88},
        "term paper":  {"Dick": 89, "Jane": 87}
    },
    "cool": {"Dick": true, "Jane": true},
    "misc": null
}

Many web services, such as Twitter, use JSON in their APIs, because another JSON goal is to be “easy for machines to parse and generate”. JSON is based on the JavaScript ECMA standard [6] in which it is native, and is extremely well documented.

JSON Primer

The documentation on json.org’s main page includes several train-track style graphics that best explain JSON usage, but here is a short primer:

  • There are two main types of JSON objects, a JSONObject and a JSONArray.
  • A JSONObject is enclosed in braces and consists of a collection of unordered key-value pairs separated by a commas. Each key-value pair is separated by a colon, with the key given before the value. In the example above, “students” is a key and its value is the JSONArray [“Dick”, “Jane”]. Keys must be strings, as explained below.
  • A JSONArray is enclosed in brackets and is ordered array of valid JSON types.
  • Items in a JSONObject or JSONArray may be one of 7 types: string, number, JSONObject, JSONArray, true, false, or null.
  • Strings are always enclosed in double-quotes and may contain backslashed escapes such as newline (\n), tab (\t), double-quotes (\”), backslash (\\) etc.
  • Numbers can be integers, floats, and scientific notation.
  • JSON interprets true and false as booleans (or logicals), and null as nothing.

There are several options to use JSON in Matlab, depending on what JSON parsing interface you wish to use. Matlab can use external libraries such as Java, .NET and C that allow us to use different implementations of the standard, including the original Java-based implementation by Douglas Crockford [7] himself, the primary author of JavaScript of which JSON is a subset. A full list of JSON implementations is given on the main website along with its documentation. Here is a short list of some libraries:

JSONlab

The most popular and mature Matlab implementation is JSONlab, which was started in 2011 by a Qianqian Fang, a medical researcher at Massachusetts General Hospital. It is available on the Matlab File Exchange [8], on SourceForge [9] and via a Subversion repository. The latest version is 1.0beta that includes BSON, a variant of JSON used in MongoDB, which compresses JSON data into a binary format. JSONlab is based in part on earlier JSON-Matlab implementations that are now deprecated: JSON Parser [14] (2009) by Joel Feenstra, another JSON Parser [15] (2011) by François Glineur, and Highly portable JSON-input parser [16] (2009) by Nedialko.
JSONlab converts both strings and files given by filename directly into Matlab structures and vice-versa. For example:

>> loadjson('{"this": "that", "foo": [1,2,3], "bar": ["a", "b", "c"]}')
ans =
    this: 'that'
    foo: [1 2 3]
    bar: {'a'  'b'  'c'}
>> s = struct('this', {'a', 'b'}, 'that', {1,2})
s =
1x2 struct array with fields:
    this
    that
>> j = savejson(s)
j =
{
    "s": [
        {
            "this": "a",
            "that": 1
        },
        {
            "this": "b",
            "that": 2
        }
    ]
}

JSONlab will nest structures as necessary and translates the JSON types into the appropriate Matlab types and vice-versa. JSONlab is well documented, easy and fast. It is reliable because it is well-maintained, has been around for several years and has many users. It is open source and issues and contributions are welcomed.

org.json (aka JSON-Java)

This is the Java implementation of JSON by the creator JSON and JavaScript, Douglas Crockford. This version is very well documented and under active development, but since there are no releases and only one branch, it could be considered the development branch. There are several other popular Java implementations listed on the JSON.org website.
The JSON library itself is called json.jar or org.json.jar. The easiest way to use it in Matlab is to add it to your java class path and then use it as if you were calling Java code. I put together a gist of examples and links [17] for your reference. In particular take a look at orgJSONdemo.m which has several examples of creating JSON objects and then using them. I addition, take a look at this CSSM newsgroup thread [18].
How to add the jar file to your java class path depends on your version of Matlab: starting in R2012b, Matlab switched from using classpath.txt in your Matlab workspace to using javaclasspath.txt [19], which is much easier (however, see here [20]). Make a file in your Matlab workspace, usually /home/MATLAB or /home/documents/matlab (e.g. on windows 7: c:\users\you\documents\matlab), called “javaclasspath.txt” and put the full path to your jar file. For example if you put the jar file in a MATLAB/JSON/ folder, then put the following line (on windows 7) in javaclasspath.txt:
the path specified in the javaclasspath.txt file should be the path to the actual jar file, so assuming your jar is called json.jar then you would put this path in your file:

C:\Users\your-user-name\Documents\MATLAB\JSON\json.jar

You must restart Matlab before this change takes effect. An alternate method is to load the jar file dynamically to Matlab’s Java classpath, using javaaddpath(‘path\to\json.jar’).
All this is pretty straight-forward in Matlab R2013b and newer, which use Java 7. json.org was implemented in Java 7 as javax.json [21], and so can be used with Matlab R2013b and newer. Matlab versions R2013a and earlier use Java 6, so another Java implementation must be used. You can either download a pre-compiled JAR file from my dropbox [22], or compile the source files on your system as follows:

  1. Confirm the version of Java used in Matlab by typing
    >> version -java
    Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) 64-Bit Server VM mixed mode
    
  2. Download and install the corresponding Java JDK from Oracle or OpenJDK
  3. Obtain the source by cloning the repository or downloading a tar/zip-ball [23]
  4. If necessary, extract the source then browse to the “src” folder
  5. Compile the source into a class files from the command line:
    C:\> C:\Program Files\Java\jdk1.7.0_45\bin\javac -verbose -sourcepath org\json\ -source 1.6 -target 1.6 -d ..\bin\ org\json\*.java org\json\zip\*.java
  6. Browse the created “bin” folder
  7. Archive the class files into a jar file:
    C:\> C:\Program Files\Java\jdk1.7.0_45\bin\jar -cvf JSON.jar org\
  8. Add the new jar file to the Matlab static Java classpath, which will depend on what version of Matlab you have:
    1. Matlab <= 2012a [24]:
      • Find the system classpath.txt file by typing:
        >> [matlabroot '\toolbox\local\classpath.txt']
        C:\Program Files\MATLAB\R2012a\toolbox\local\classpath.txt
        
      • Copy the classpath to your working folder and append the path the jar file to the end. Use hash marks to comment lines.
         
    2. Matlab >= 2012b [25]: create a new file called “javaclasspath.txt” in your working folder with the path of the new jar file in it. Use hash marks for comments.
       
  9. Restart Matlab to enable the jar file within Matlab.

Using the Java library is the same as using any Java library in Matlab. One nice feature is that tabbing after typing “object.” gives a pop-up list of available properties and methods, including inherited ones. Here are some simple usage examples:

>> j1 = org.json.JSONObject('{"this": "that", "foo": [1,2,3], "bar": ["a", "b", "c"]}')
>> j2 = j1.put('hello', 'world')
j2 =
{"hello":"world", "foo":[1,2,3], "bar":["a","b","c"], "this":"that"}
>> w = j1.getString('hello')
ans =
world

Watch out: the output is actually a java.lang.String object; use char() to convert it into a Matlab string:

>> char(w)
ans =
world

There is no easy way to convert a JSONArray to an array, so you can either loop over it, or convert it to a string and parse it. Note that JSONArray indexes start from 0, as in Java (contrary to Matlab indexes, which start at 1)

>> f = j1.get('foo')
f =
[1,2,3]
>> for n = 1:f.length,  fa(n)=f.get(n-1);  end
>> fa
fa =
     1     2     3

Json.NET and fastJSON

These libraries require you to add add the path of the .NET dll to Matlab using NET.addAssembly. For fastJSON, since binaries are not available, you will also need to compile the .NET dll. I’ll leave it to the reader to investigate further, independently.

Categories: Guest bloggers, Java, Low risk of breaking in future versions


18 Comments (Open | Close)

18 Comments To "JSON-Matlab integration"

#1 Comment By Mark Mikofski On April 29, 2014 @ 22:15

FYI: [32] can read a MAT file into Python.

#2 Comment By Rune Juhl Jacobsen On May 14, 2014 @ 04:08

There’s also [33] . While I haven’t benchmarked it, it should be a lot faster than Matlab-only implementations.

#3 Pingback By Working with JSON & Matlab | Alejandro Clemotte On September 6, 2014 @ 02:10

[…] A good post talking about several option is this. […]

#4 Comment By Mark Mikofski On April 23, 2015 @ 15:37

Just saw this [33]. there are prebuilt windows binaries in bin/

#5 Comment By mark mikofski On August 4, 2015 @ 12:14

I wish I had put more detail into using Newtonsoft JSON.net. Here’s a [34]

% download JSON.net from https://github.com/JamesNK/Newtonsoft.Json/releases
% extract into MATLAB folder
% ====

% add assembly (assuming not registered in GAC)
asm = NET.addAssembly('%HOME%\Documents\MATLAB\Json70r1\bin\Net35\Newtonsoft.Json.dll')

% DESERIALIZING JSON OBJECT
% =========================
% using the following example:
% {"inputs":
%   {"module":
%     {"name": "solarpanel-435",
%      "nameplate": 435
%     }
%   },
%   {"request":
%     {"startdate": [2015,1,1,1,0,0],
%      "enddate": [2015,12,31,23,0,0]
%     }
%   }
% }


% get source using io
str_data = fileread('path/to/file.json')

% use Json.Convrters.DeserializeObject(str_data)
json_data = Newtonsoft.Json.JsonConvert.DeserializeObject(str_data)

% getting value by key
inputs = json_data.GetValue('inputs') % get keys
module = inputs.GetValue('module')

% getting value of Newtonsoft.Json.Linq.JValue
name = module.GetValue('name').Value() % return value of name
nameplate = module.GetValue('nameplate').Value()

% getting items in JArray
startdate(1) = inputs.GetValue('request').Item(0)
startdate(2) = inputs.GetValue('request').Item(1)
startdate(3) = inputs.GetValue('request').Item(2)
startdate(4) = inputs.GetValue('request').Item(3)
startdate(5) = inputs.GetValue('request').Item(4)
startdate(6) = inputs.GetValue('request').Item(5)

% prettyprint output
json_data.ToString()

% SERIALIZE LINQ JSON OBJECT
% ==========================
% create a LINQ JObject
json_obj = Newtonsoft.Json.Linq.JObject() % create object

% view methods
methodsview(json_obj) % view all methods for JObject

% add values, objects and arrays
json_obj.Add('this', Newtonsoft.Json.Linq.JValue('that'))
json_obj.Add('foo', Newtonsoft.Json.Linq.JArray([10,20,30]))
json_obj.Add('bar', Newtonsoft.Json.Linq.JArray({'x','y','z'}))

% prettyprint
json_obj.ToString() % pretty print

% serialize json object
json_str = json_obj.Add('foo', Newtonsoft.Json.Linq.JArray([10,20,30]))
fid = fopen('outputfile.json')
fwrite(fid,json_str)
fclose(fid)

#6 Comment By آموزش متلب On November 18, 2015 @ 09:08

Very Nice
TNX.

#7 Comment By ET On December 11, 2015 @ 08:25

I think these are semi undocumented in the latest Matlab versions (i.e. R2015a or R2015b) but they are much faster then most other solutions:

jsonString = matlab.internal.webservices.toJSON(s);
matlab.internal.webservices.fromJSON(jsonString);

#8 Comment By Brad Stiritz On December 30, 2015 @ 21:08

ET, I tried your code without success in R2015a :

 
>> matlab.internal.webservices.toJSON('abc')
Undefined variable "matlab" or class "matlab.internal.webservices.toJSON".

#9 Comment By Yair Altman On December 31, 2015 @ 00:38

@Brad – toJSON() and fromJSON() were added in R2015b

#10 Comment By oro77 On March 31, 2016 @ 06:25

I am using the following command to create the JSON string.

jsonString = matlab.internal.webservices.toJSON(s);

It works but if my structure is using a real like below.

s = struct('this', {'a', 'b'}, 'that', {0.1, 2})

jsonString will return

[{"this":"a","that":0.10000000000000001},{"this":"b","that":2}]

Why is it 0.10000000000000001 instead of 0.1 ?
How can I correct this ?

#11 Comment By Malcolm Lidierth On March 31, 2016 @ 08:12

For a long answer:
[35], by David Goldberg, published in the March, 1991 issue of Computing Surveys. Copyright 1991, Association for Computing Machinery, Inc.

Short answer:
Just as 1/3 can not be exactly represented in decimal, 1/10 has no exact representation in binary.

The java.lang.Double class is probably underused by MATLABers: its toString() method returns a string representation of a double that uses the minimum number of digits required to exactly reproduce that double during deserialisation (i.e to get back to that member of the subset of numbers represented in IEEE double).

java.lang.Double uses the [36]

#12 Comment By oro77 On March 31, 2016 @ 11:19

Thank you for your reply.
So the best way to keep 0.1 would be to store in my structure a string instead of a double value.

#13 Comment By Yair Altman On March 31, 2016 @ 11:26

@oro77 – I would think that it would make more sense to simply round off the insignificant digits upon loading/displaying (in those rare cases where this difference in LSB makes any difference), rather than store string representations in the JSON payload.

#14 Comment By oro77 On March 31, 2016 @ 11:45

@Yair Altman – Thank you for your advice. I was thinking about rounding off it but the user may want to edit the json file in a text editor and he may find awkward about the insignificant digits. It is hard to decide what is the best solution. Is there something wrong about storing string representations in the JSON payload ?

#15 Comment By Malcolm Lidierth On March 31, 2016 @ 20:46

@oro77
The number of digits used depends on the JSon library and how it does the formatting. Sun/Oracle/openJDK provide a full spec for the java.lang.Double.toString() method. Remembering that MATLAB calls that method to get the text to display in the MATLAB Command Window for Java objects including Double, the following may be informative:

>> a = java.lang.Double('0.1')
a =
0.1
 
>> b = java.lang.Double('0.10000000000000001')
b =
0.1 
 
>> a==b
ans =
     1

>> java.lang.Double(0.1)==java.lang.Double('0.1')
ans =
     1

#16 Comment By Oleg On June 26, 2016 @ 00:59

As of R2016a the core of matlab.internal.webservices.toJSON() and matlab.internal.webservices.fromJSON() are in mex, hence very fast.

#17 Comment By Oliver Woodford On September 19, 2016 @ 01:44

Reading from a JSON still isn’t as fas as it could be. My [37] is over 10x faster than fromJSON(fileread('filename.json')).

#18 Comment By Mariusz Zaleski On August 15, 2016 @ 15:45

Hi,

Is there anything that would work in C# parsing JSON to MatLab native types? (MWCharArray, MWNumericalArray etc)


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/json-matlab-integration

URLs in this post:

[1] Mark Mikofski: http://poquitopicante.blogspot.com

[2] JGIT-Matlab integration: http://undocumentedmatlab.com/blog/jgit-matlab-integration/

[3] GIT support to Simulink projects: http://www.mathworks.com/help/simulink/ug/set-up-git-source-control.html

[4] JMatIO: http://sourceforge.net/projects/jmatio/

[5] http://json.org: http://json.org

[6] JavaScript ECMA standard: http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf

[7] Douglas Crockford: http://en.wikipedia.org/wiki/Douglas_Crockford

[8] JSONlab: http://www.mathworks.com/matlabcentral/fileexchange/33381-jsonlab-a-toolbox-to-encode-decode-json-files-in-matlab-octave

[9] SourceForge: http://iso2mesh.sourceforge.net/cgi-bin/index.cgi?jsonlab

[10] org.json: http://www.json.org/java/index.html

[11] an archived link: https://web.archive.org/web/20160118153748/http://www.json.org/java/index.html

[12] Json.NET: http://james.newtonking.com/json

[13] fastJSON: http://www.codeproject.com/Articles/159450/fastJSON

[14] JSON Parser: http://www.mathworks.com/matlabcentral/fileexchange/20565-json-parser

[15] another JSON Parser: http://www.mathworks.com/matlabcentral/fileexchange/23393-another-json-parser

[16] Highly portable JSON-input parser: http://www.mathworks.com/matlabcentral/fileexchange/25713-highly-portable-json-input-parser

[17] gist of examples and links: https://gist.github.com/mikofski/2492355

[18] CSSM newsgroup thread: https://www.mathworks.com/matlabcentral/newsreader/view_thread/330728

[19] javaclasspath.txt: http://www.mathworks.com/help/matlab/matlab_external/bringing-java-classes-and-methods-into-matlab-workspace.html#f111065

[20] see here: http://undocumentedmatlab.com/blog/matlab-installation-take-2/#comment-110967

[21] javax.json: http://docs.oracle.com/javaee/7/api/javax/json/package-summary.html

[22] from my dropbox: http://dl.dropbox.com/u/19049582/JSON.jar

[23] downloading a tar/zip-ball: http://json.org/java

[24] Matlab <= 2012a: http://www.mathworks.com/help/releases/R2012a/techdoc/matlab_external/f4863.html#f4867

[25] Matlab >= 2012b: http://www.mathworks.com/help/releases/R2012b/matlab/matlab_external/bringing-java-classes-and-methods-into-matlab-workspace.html#f4867

[26] JGit-Matlab integration : https://undocumentedmatlab.com/articles/jgit-matlab-integration

[27] Matlab installation woes : https://undocumentedmatlab.com/articles/matlab-installation-woes

[28] Inter-Matlab data transfer with memcached : https://undocumentedmatlab.com/articles/inter-matlab-data-transfer-with-memcached

[29] Using Groovy in Matlab : https://undocumentedmatlab.com/articles/using-groovy-in-matlab

[30] JGraph in Matlab figures : https://undocumentedmatlab.com/articles/jgraph-in-matlab-figures

[31] Matlab-Java interface using a static control : https://undocumentedmatlab.com/articles/matlab-java-interface-using-static-control

[32] : http://docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.io.loadmat.html

[33] : https://github.com/christianpanton/matlab-json

[34] : https://gist.github.com/mikofski/2492355#file-netjsondemo-m

[35] : http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

[36] : http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html

[37] : https://uk.mathworks.com/matlabcentral/fileexchange/59166-json-read

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.