From 4bd7dc5633f8379da6e3706a5a8f85f19833c303 Mon Sep 17 00:00:00 2001 From: jos Date: Wed, 18 Feb 2015 20:34:43 +0100 Subject: [PATCH] Implemented toJSON and fromJSON and a reviver for most data types --- lib/function/utils/clone.js | 10 +-- lib/json/reviver.js | 34 ++++++++++ lib/math.js | 5 ++ lib/type/BigNumber.js | 28 ++++++++ lib/type/Complex.js | 6 +- lib/type/Help.js | 6 +- lib/type/Index.js | 22 +++++++ lib/type/Matrix.js | 33 +++------- lib/type/Range.js | 24 +++++++ lib/type/ResultSet.js | 22 +++++++ lib/type/Unit.js | 38 +++++++++-- test/json/replacer.test.js | 80 +++++++++++++++++++++++ test/json/reviver.test.js | 124 ++++++++++++++++++++++++++++++++++++ test/type/BigNumber.test.js | 18 ++++++ test/type/Complex.test.js | 10 +-- test/type/Index.test.js | 20 ++++++ test/type/Matrix.test.js | 26 ++------ test/type/Range.test.js | 19 ++++++ test/type/ResultSet.test.js | 14 ++++ test/type/Unit.test.js | 23 +++++++ 20 files changed, 495 insertions(+), 67 deletions(-) create mode 100644 lib/json/reviver.js create mode 100644 lib/type/BigNumber.js create mode 100644 test/json/replacer.test.js create mode 100644 test/json/reviver.test.js create mode 100644 test/type/BigNumber.test.js diff --git a/lib/function/utils/clone.js b/lib/function/utils/clone.js index 88bc09dc1..680c90c1c 100644 --- a/lib/function/utils/clone.js +++ b/lib/function/utils/clone.js @@ -13,11 +13,11 @@ module.exports = function (math) { * * Examples: * - * math.clone(3.5); // returns number 3.5 - * math.clone(2 - 4i); // returns Complex 2 - 4i - * math.clone(45 deg); // returns Unit 45 deg - * math.clone([[1, 2], [3, 4]]); // returns Array [[1, 2], [3, 4]] - * math.clone("hello world"); // returns string "hello world" + * math.clone(3.5); // returns number 3.5 + * math.clone(math.complex('2 - 4i'); // returns Complex 2 - 4i + * math.clone(math.unit(45, 'deg')); // returns Unit 45 deg + * math.clone([[1, 2], [3, 4]]); // returns Array [[1, 2], [3, 4]] + * math.clone("hello world"); // returns string "hello world" * * @param {*} x Object to be cloned * @return {*} A clone of object x diff --git a/lib/json/reviver.js b/lib/json/reviver.js new file mode 100644 index 000000000..81d1bc5b7 --- /dev/null +++ b/lib/json/reviver.js @@ -0,0 +1,34 @@ +'use strict'; + +var BigNumber = require('../type/BigNumber'); +var Complex = require('../type/Complex'); +var Index = require('../type/Index'); +var Matrix = require('../type/Matrix'); +var Range = require('../type/Range'); +var ResultSet = require('../type/ResultSet'); +var Unit = require('../type/Unit'); + +/** + * Instantiate mathjs data types from their JSON representation + * @param {string} key + * @param {*} value + * @returns {*} Returns the revived object + */ +function reviver(key, value) { + var type = value && value['@type']; + + switch (type) { + case 'BigNumber': return BigNumber.fromJSON(value); + case 'Complex': return Complex.fromJSON(value); + case 'Index': return Index.fromJSON(value); + case 'Matrix': return Matrix.fromJSON(value); + case 'Range': return Range.fromJSON(value); + case 'ResultSet': return ResultSet.fromJSON(value); + case 'Unit': return Unit.fromJSON(value); + // TODO: add Help + } + + return value; +} + +module.exports = reviver; diff --git a/lib/math.js b/lib/math.js index 01ddf2a9a..e6551d2d0 100644 --- a/lib/math.js +++ b/lib/math.js @@ -171,6 +171,11 @@ function create (config) { math.expression.Parser = require('./expression/Parser'); math.expression.docs = require('./expression/docs/index'); + // serialization utilities + math.json = { + reviver: require('./json/reviver') + }; + // expression parser require('./function/expression/compile')(math, _config); require('./function/expression/eval')(math, _config); diff --git a/lib/type/BigNumber.js b/lib/type/BigNumber.js new file mode 100644 index 000000000..c75f7511c --- /dev/null +++ b/lib/type/BigNumber.js @@ -0,0 +1,28 @@ +var BigNumber = require('decimal.js'); + +// FIXME: replace all require('decimal.js') with require('./BigNumber'). + +/** + * Get a JSON representation of a BigNumber containing + * type information + * @returns {Object} Returns a JSON object structured as: + * `{"@type": "BigNumber", "value": "0.2"}` + */ +BigNumber.prototype.toJSON = function () { + return { + '@type': 'BigNumber', + value: this.toString() + }; +}; + +/** + * Instantiate a BigNumber from a JSON object + * @param {Object} json a JSON object structured as: + * `{"@type": "BigNumber", "value": "0.2"}` + * @return {BigNumber} + */ +BigNumber.fromJSON = function (json) { + return new BigNumber(json.value); +}; + +module.exports = BigNumber; diff --git a/lib/type/Complex.js b/lib/type/Complex.js index fa372cb0d..efcead706 100644 --- a/lib/type/Complex.js +++ b/lib/type/Complex.js @@ -453,14 +453,14 @@ Complex.prototype.toJSON = function () { /** * Create a Complex number from a JSON object - * @param {Object} obj A JSON Object structured as + * @param {Object} json A JSON Object structured as * {"@type": "Complex", "re": 2, "im": 3} * All properties are optional, default values * for `re` and `im` are 0. * @return {Complex} Returns a new Complex number */ -Complex.fromJSON = function (obj) { - return new Complex(obj); +Complex.fromJSON = function (json) { + return new Complex(json); }; /** diff --git a/lib/type/Help.js b/lib/type/Help.js index 0b96d6e9b..595924c03 100644 --- a/lib/type/Help.js +++ b/lib/type/Help.js @@ -94,12 +94,12 @@ Help.prototype.toJSON = function () { /** * Instantiate a Help object from a JSON object - * @param {Object} obj + * @param {Object} json * @param {Object} math An instance of mathjs * @returns {Help} Returns a new Help object */ -Help.prototype.fromJSON = function (obj, math) { - return new Help(obj, math); +Help.prototype.fromJSON = function (json, math) { + return new Help(json, math); }; /** diff --git a/lib/type/Index.js b/lib/type/Index.js index fcd43a3a9..7e2867d1c 100644 --- a/lib/type/Index.js +++ b/lib/type/Index.js @@ -265,5 +265,27 @@ Index.prototype.toString = function () { return '[' + strings.join(', ') + ']'; }; +/** + * Get a JSON representation of the Index + * @returns {Object} Returns a JSON object structured as: + * `{"@type": "Index", "ranges": [{"@type": "Range", start: 0, end: 10, step:1}, ...]}` + */ +Index.prototype.toJSON = function () { + return { + '@type': 'Index', + ranges: this._ranges + }; +}; + +/** + * Instantiate an Index from a JSON object + * @param {Object} json A JSON object structured as: + * `{"@type": "Index", "ranges": [{"@type": "Range", start: 0, end: 10, step:1}, ...]}` + * @return {Index} + */ +Index.fromJSON = function (json) { + return Index.create(json.ranges); +}; + // exports module.exports = Index; diff --git a/lib/type/Matrix.js b/lib/type/Matrix.js index f09d53624..bab489353 100644 --- a/lib/type/Matrix.js +++ b/lib/type/Matrix.js @@ -492,40 +492,25 @@ Matrix.prototype.toString = function () { }; /** - * Get a JSON representation of the matrix data. - * @returns {Object} Returns an object like - * {"@type": "Matrix", "data": [...]} + * Get a JSON representation of the matrix + * @returns {Object} */ Matrix.prototype.toJSON = function () { return { "@type": "Matrix", - "data": this.map(function (entry) { - return entry && typeof entry.toJSON === 'function' ? entry.toJSON() : entry; - }).toArray() + "data": this._data } }; /** * Generate a matrix from a JSON object - * @param {Object || Array} obj An object structured like - * `{"@type": "Matrix", data: []}`, - * or is an array `[...]` - * where all entries are supposed to be - * JSON objects of data types. - * @param {Object} math An instance of mathjs, used to find - * available types under `math.type` - * @returns {Object} Returns an object like - * {"@type": "Matrix", "data": [...]} + * @param {Object} json An object structured like + * `{"@type": "Matrix", data: []}`, + * where @type is optional + * @returns {Matrix} */ -Matrix.fromJSON = function (obj, math) { - var matrix = new Matrix(isArray(obj) ? obj : obj.data); - - return matrix.map(function (entry) { - var type = entry && entry['@type']; - var constructor = type && math.type[type]; - var fromJSON = constructor && constructor.fromJSON; - return fromJSON ? fromJSON(entry, math) : entry; - }); +Matrix.fromJSON = function (json) { + return new Matrix(json.data); }; /** diff --git a/lib/type/Range.js b/lib/type/Range.js index 7bfa5d68f..368047280 100644 --- a/lib/type/Range.js +++ b/lib/type/Range.js @@ -265,5 +265,29 @@ Range.prototype.toString = function () { return this.format(); }; +/** + * Get a JSON representation of the range + * @returns {Object} Returns a JSON object structured as: + * `{"@type": "Range", "start": 2, "end": 4, "step": 1}` + */ +Range.prototype.toJSON = function () { + return { + '@type': 'Range', + start: this.start, + end: this.end, + step: this.step + }; +}; + +/** + * Instantiate a Range from a JSON object + * @param {Object} json A JSON object structured as: + * `{"@type": "Range", "start": 2, "end": 4, "step": 1}` + * @return {Range} + */ +Range.fromJSON = function (json) { + return new Range(json.start, json.end, json.step); +}; + // exports module.exports = Range; diff --git a/lib/type/ResultSet.js b/lib/type/ResultSet.js index d1fb1ee8d..2d3e74233 100644 --- a/lib/type/ResultSet.js +++ b/lib/type/ResultSet.js @@ -29,4 +29,26 @@ ResultSet.prototype.toString = function () { return '[' + this.entries.join(', ') + ']'; }; +/** + * Get a JSON representation of the ResultSet + * @returns {Object} Returns a JSON object structured as: + * `{"@type": "ResultSet", "entries": [...]}` + */ +ResultSet.prototype.toJSON = function () { + return { + '@type': 'ResultSet', + entries: this.entries + }; +}; + +/** + * Instantiate a ResultSet from a JSON object + * @param {Object} json A JSON object structured as: + * `{"@type": "ResultSet", "entries": [...]}` + * @return {ResultSet} + */ +ResultSet.fromJSON = function (json) { + return new ResultSet(json.entries); +}; + module.exports = ResultSet; diff --git a/lib/type/Unit.js b/lib/type/Unit.js index f44e7463e..83d1d3d0c 100644 --- a/lib/type/Unit.js +++ b/lib/type/Unit.js @@ -259,13 +259,13 @@ Unit.prototype._normalize = function(value) { }; /** - * Unnormalize a value, based on its currently set unit + * Denormalize a value, based on its currently set unit * @param {Number} value * @param {Number} [prefixValue] Optional prefix value to be used - * @return {Number} unnormalized value + * @return {Number} denormalized value * @private */ -Unit.prototype._unnormalize = function (value, prefixValue) { +Unit.prototype._denormalize = function (value, prefixValue) { if (prefixValue == undefined) { return value / this.unit.value / this.prefix.value - this.unit.offset; } @@ -384,7 +384,7 @@ Unit.prototype.to = function (valuelessUnit) { */ Unit.prototype.toNumber = function (valuelessUnit) { var other = this.to(valuelessUnit); - return other._unnormalize(other.value, other.prefix.value); + return other._denormalize(other.value, other.prefix.value); }; @@ -396,6 +396,32 @@ Unit.prototype.toString = function() { return this.format(); }; +/** + * Get a JSON representation of the unit + * @returns {Object} Returns a JSON object structured as: + * `{"@type": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}` + */ +Unit.prototype.toJSON = function () { + return { + '@type': 'Unit', + value: this._denormalize(this.value), + unit: this.prefix.name + this.unit.name, + fixPrefix: this.fixPrefix + }; +}; + +/** + * Instantiate a Unit from a JSON object + * @param {Object} json A JSON object structured as: + * `{"@type": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}` + * @return {Unit} + */ +Unit.fromJSON = function (json) { + var unit = new Unit(json.value, json.unit); + unit.fixPrefix = json.fixPrefix || false; + return unit; +}; + /** * Returns the string representation of the unit. * @return {String} @@ -416,12 +442,12 @@ Unit.prototype.format = function(options) { if (this.value !== null && !this.fixPrefix) { var bestPrefix = this._bestPrefix(); - value = this._unnormalize(this.value, bestPrefix.value); + value = this._denormalize(this.value, bestPrefix.value); str = number.format(value, options) + ' '; str += bestPrefix.name + this.unit.name; } else { - value = this._unnormalize(this.value); + value = this._denormalize(this.value); str = (this.value !== null) ? (number.format(value, options) + ' ') : ''; str += this.prefix.name + this.unit.name; } diff --git a/test/json/replacer.test.js b/test/json/replacer.test.js new file mode 100644 index 000000000..4410204ec --- /dev/null +++ b/test/json/replacer.test.js @@ -0,0 +1,80 @@ +var assert= require('assert'); +var Complex = require('../../lib/type/Complex'); +var Range = require('../../lib/type/Range'); +var Index = require('../../lib/type/Index'); +var Matrix = require('../../lib/type/Matrix'); +var Unit = require('../../lib/type/Unit'); +var BigNumber = require('../../lib/type/BigNumber'); +var ResultSet = require('../../lib/type/ResultSet'); + +describe('replacer', function () { + + it('should stringify generic JSON', function () { + var data = {foo: [1,2,3], bar: null, baz: 'str'}; + var json = '{"foo":[1,2,3],"bar":null,"baz":"str"}'; + assert.deepEqual(JSON.stringify(data), json); + }); + + it('should stringify a Complex number', function () { + var c = new Complex(2, 4); + var json = '{"@type":"Complex","re":2,"im":4}'; + + assert.deepEqual(JSON.stringify(c), json); + }); + + it('should stringify a BigNumber', function () { + var b = new BigNumber(5); + var json = '{"@type":"BigNumber","value":"5"}'; + + assert.deepEqual(JSON.stringify(b), json); + }); + + it('should stringify a Range', function () { + var r = new Range(2, 10); + var json = '{"@type":"Range","start":2,"end":10,"step":1}'; + assert.deepEqual(JSON.stringify(r), json); + }); + + it('should stringify an Index', function () { + var i = new Index([0, 10], 2); + var json = '{"@type":"Index","ranges":[' + + '{"@type":"Range","start":0,"end":10,"step":1},' + + '{"@type":"Range","start":2,"end":3,"step":1}' + + ']}'; + assert.deepEqual(JSON.stringify(i), json); + }); + + it('should stringify a Range (2)', function () { + var r = new Range(2, 10, 2); + var json = '{"@type":"Range","start":2,"end":10,"step":2}'; + assert.deepEqual(JSON.stringify(r), json); + }); + + it('should stringify a Unit', function () { + var u = new Unit(5, 'cm'); + var json = '{"@type":"Unit","value":5,"unit":"cm","fixPrefix":false}'; + assert.deepEqual(JSON.stringify(u), json); + }); + + it('should stringify a Matrix', function () { + var m = new Matrix([[1,2],[3,4]]); + var json = '{"@type":"Matrix","data":[[1,2],[3,4]]}'; + + assert.deepEqual(JSON.stringify(m), json); + }); + + it('should stringify a ResultSet', function () { + var r = new ResultSet([1,2,new Complex(3,4)]); + var json = '{"@type":"ResultSet","entries":[1,2,{"@type":"Complex","re":3,"im":4}]}'; + assert.deepEqual(JSON.stringify(r), json); + }); + + it('should stringify a Matrix containing a complex number', function () { + var c = new Complex(4, 5); + var m = new Matrix([[1,2],[3,c]]); + var json = '{"@type":"Matrix","data":[[1,2],[3,{"@type":"Complex","re":4,"im":5}]]}'; + + assert.deepEqual(JSON.stringify(m), json); + }); + +}); diff --git a/test/json/reviver.test.js b/test/json/reviver.test.js new file mode 100644 index 000000000..42c594d52 --- /dev/null +++ b/test/json/reviver.test.js @@ -0,0 +1,124 @@ +var assert= require('assert'); +var reviver = require('../../lib/json/reviver'); +var Complex = require('../../lib/type/Complex'); +var Range = require('../../lib/type/Range'); +var Index = require('../../lib/type/Index'); +var Unit = require('../../lib/type/Unit'); +var Matrix = require('../../lib/type/Matrix'); +var BigNumber = require('../../lib/type/BigNumber'); +var ResultSet = require('../../lib/type/ResultSet'); + +describe('reviver', function () { + + it('should parse generic JSON', function () { + var json = '{"foo":[1,2,3],"bar":null,"baz":"str"}'; + var data = {foo: [1,2,3], bar: null, baz: 'str'}; + assert.deepEqual(JSON.parse(json, reviver), data); + }); + + it('should parse a stringified complex number', function () { + var json = '{"@type":"Complex","re":2,"im":4}'; + var c = new Complex(2, 4); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Complex); + assert.deepEqual(obj, c); + }); + + it('should parse a stringified BigNumber', function () { + var json = '{"@type":"BigNumber","value":"0.2"}'; + var b = new BigNumber(0.2); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof BigNumber); + assert.deepEqual(obj, b); + }); + + it('should parse a stringified Range', function () { + var json = '{"@type":"Range","start":2,"end":10}'; + var r = new Range(2, 10); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Range); + assert.deepEqual(obj, r); + }); + + it('should parse a stringified Unit', function () { + var json = '{"@type":"Unit","value":5,"unit":"cm","fixPrefix":false}'; + var u = new Unit(5, 'cm'); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Unit); + assert.deepEqual(obj, u); + }); + + it('should parse a stringified Range (2)', function () { + var json = '{"@type":"Range","start":2,"end":10,"step":2}'; + var r = new Range(2, 10, 2); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Range); + assert.deepEqual(obj, r); + }); + + it('should parse a stringified ResultSet', function () { + var json = '{"@type":"ResultSet","entries":[1,2,{"@type":"Complex","re":3,"im":4}]}'; + var r = new ResultSet([1,2,new Complex(3,4)]); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof ResultSet); + assert.deepEqual(obj, r); + }); + + it('should parse a stringified Index', function () { + var json = '{"@type":"Index","ranges":[' + + '{"@type":"Range","start":0,"end":10,"step":1},' + + '{"@type":"Range","start":2,"end":3,"step":1}' + + ']}'; + var i = new Index([0, 10], 2); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Index); + assert.deepEqual(obj, i); + }); + + it('should parse a stringified Index (2)', function () { + var json = '{"@type":"Index","ranges":[[0, 10],2]}'; + var i = new Index([0, 10], 2); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Index); + assert.deepEqual(obj, i); + }); + + it('should parse a stringified Matrix', function () { + var json = '{"@type":"Matrix","data":[[1,2],[3,4]]}'; + var m = new Matrix([[1,2],[3,4]]); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Matrix); + assert.deepEqual(obj, m); + }); + + it('should parse a stringified Matrix containing a complex number', function () { + var json = '{"@type":"Matrix","data":[[1,2],[3,{"@type":"Complex","re":4,"im":5}]]}'; + var c = new Complex(4, 5); + var m = new Matrix([[1,2],[3,c]]); + + var obj = JSON.parse(json, reviver); + + assert(obj instanceof Matrix); + assert(obj._data[1][1] instanceof Complex); + assert.deepEqual(obj, m); + }); + +}); diff --git a/test/type/BigNumber.test.js b/test/type/BigNumber.test.js new file mode 100644 index 000000000..7b9e4cf21 --- /dev/null +++ b/test/type/BigNumber.test.js @@ -0,0 +1,18 @@ +var assert = require('assert'); +var BigNumber = require('../../lib/type/BigNumber'); + + +describe('BigNumber', function () { + + it('toJSON', function () { + assert.deepEqual(new BigNumber(5).toJSON(), {'@type': 'BigNumber', value: '5'}); + }); + + it('fromJSON', function () { + var b = BigNumber.fromJSON({value: '5'}); + assert.ok(b instanceof BigNumber); + assert.strictEqual(b.toString(), '5'); + assert.deepEqual(b, new BigNumber(5)); + }); + +}); diff --git a/test/type/Complex.test.js b/test/type/Complex.test.js index ca46326f4..e72985b28 100644 --- a/test/type/Complex.test.js +++ b/test/type/Complex.test.js @@ -1,8 +1,8 @@ // test data type Complex -var assert = require('assert'), - Unit = require('../../lib/type/Unit'), - Complex = require('../../lib/type/Complex'); +var assert = require('assert'); +var Unit = require('../../lib/type/Unit'); +var Complex = require('../../lib/type/Complex'); describe('Complex', function () { @@ -304,12 +304,12 @@ describe('Complex', function () { }); }); - it('should return a JSON representation using toJSON', function () { + it('toJSON', function () { assert.deepEqual(new Complex(2, 4).toJSON(), {'@type': 'Complex', re: 2, im: 4}); assert.deepEqual(new Complex(3, 0).toJSON(), {'@type': 'Complex', re: 3, im: 0}); }); - it('should create a complex number from a JSON object', function () { + it('fromJSON', function () { var c1 = Complex.fromJSON({re: 2, im: 4}); assert.ok(c1 instanceof Complex); assert.strictEqual(c1.re, 2); diff --git a/test/type/Index.test.js b/test/type/Index.test.js index 38f3bc487..7da0419b8 100644 --- a/test/type/Index.test.js +++ b/test/type/Index.test.js @@ -85,6 +85,26 @@ describe('Index', function () { assert.equal(new Index([0,6,2]).toString(), '[0:2:6]'); }); + it('toJSON', function () { + assert.deepEqual(new Index([0,10], 2).toJSON(), + {'@type': 'Index', ranges: [ + new Range(0, 10, 1), + new Range(2, 3, 1) + ]}); + }); + + it('fromJSON', function () { + var json = {ranges: [ + new Range(0, 10, 1), + new Range(2, 3, 1) + ]}; + var i1 = new Index([0,10], 2); + + var i2 = Index.fromJSON(json); + assert.ok(i2 instanceof Index); + assert.deepEqual(i2, i1); + }); + it('should get the range for a given dimension', function () { var index = new Index(2, [0, 8, 2], [3,-1,-1]); diff --git a/test/type/Matrix.test.js b/test/type/Matrix.test.js index 7c4848a3d..f26248629 100644 --- a/test/type/Matrix.test.js +++ b/test/type/Matrix.test.js @@ -55,41 +55,25 @@ describe('matrix', function() { }); it('toJSON', function() { - assert.deepEqual(new Matrix([[1,2],[3,new Complex(4,5)]]).toJSON(), { + assert.deepEqual(new Matrix([[1,2],[3,4]]).toJSON(), { '@type': 'Matrix', - data: [[1,2],[3,{'@type': 'Complex', re: 4, im: 5}]] + data: [[1,2],[3,4]] }); }); it('fromJSON', function() { var json = { '@type': 'Matrix', - data: [[1,2],[3,{'@type': 'Complex', re: 4, im: 5}]] + data: [[1,2],[3,4]] }; - var m = Matrix.fromJSON(json, math); + var m = Matrix.fromJSON(json); assert.ok(m instanceof Matrix); assert.deepEqual(m._size, [2, 2]); assert.strictEqual(m._data[0][0], 1); assert.strictEqual(m._data[0][1], 2); assert.strictEqual(m._data[1][0], 3); - assert.ok(m._data[1][1] instanceof Complex); - assert.strictEqual(m._data[1][1].re, 4); - assert.strictEqual(m._data[1][1].im, 5); - }); - - it('fromJSON (2)', function() { - var json = [[1,2],[3,{'@type': 'Complex', re: 4, im: 5}]]; - var m = Matrix.fromJSON(json, math); - - assert.ok(m instanceof Matrix); - assert.deepEqual(m._size, [2, 2]); - assert.strictEqual(m._data[0][0], 1); - assert.strictEqual(m._data[0][1], 2); - assert.strictEqual(m._data[1][0], 3); - assert.ok(m._data[1][1] instanceof Complex); - assert.strictEqual(m._data[1][1].re, 4); - assert.strictEqual(m._data[1][1].im, 5); + assert.strictEqual(m._data[1][1], 4); }); it('format', function() { diff --git a/test/type/Range.test.js b/test/type/Range.test.js index 17a3fbaa3..2262d1d5c 100644 --- a/test/type/Range.test.js +++ b/test/type/Range.test.js @@ -246,4 +246,23 @@ describe('range', function() { }); }); + it('toJSON', function () { + assert.deepEqual(new Range(2, 4).toJSON(), {'@type': 'Range', start: 2, end: 4, step: 1}); + assert.deepEqual(new Range(0, 10, 2).toJSON(), {'@type': 'Range', start: 0, end: 10, step: 2}); + }); + + it('fromJSON', function () { + var r1 = Range.fromJSON({start: 2, end: 4}); + assert.ok(r1 instanceof Range); + assert.strictEqual(r1.start, 2); + assert.strictEqual(r1.end, 4); + assert.strictEqual(r1.step, 1); + + var r2 = Range.fromJSON({start: 0, end: 10, step: 2}); + assert.ok(r2 instanceof Range); + assert.strictEqual(r2.start, 0); + assert.strictEqual(r2.end, 10); + assert.strictEqual(r2.step, 2); + }); + }); \ No newline at end of file diff --git a/test/type/ResultSet.test.js b/test/type/ResultSet.test.js index 01e4d7b1e..45430560c 100644 --- a/test/type/ResultSet.test.js +++ b/test/type/ResultSet.test.js @@ -30,4 +30,18 @@ describe('ResultSet', function () { assert.deepEqual(r.toString(), '[1, 2, 3, 4 + 5i]'); }); + it('toJSON', function () { + var r = new ResultSet([1,2,3]); + var json = {"@type":"ResultSet","entries":[1,2,3]}; + assert.deepEqual(r.toJSON(), json); + }); + + it('fromJSON', function () { + var r1 = new ResultSet([1,2,3]); + var json = {"@type":"ResultSet","entries":[1,2,3]}; + var r2 = ResultSet.fromJSON(json); + assert(r2 instanceof ResultSet); + assert.deepEqual(r2, r1); + }); + }); \ No newline at end of file diff --git a/test/type/Unit.test.js b/test/type/Unit.test.js index c87186f07..228de2946 100644 --- a/test/type/Unit.test.js +++ b/test/type/Unit.test.js @@ -244,6 +244,29 @@ describe('unit', function() { }); + describe('json', function () { + + it('toJSON', function () { + assert.deepEqual(new Unit(5, 'cm').toJSON(), + {'@type': 'Unit', value: 5, unit: 'cm', fixPrefix: false}); + assert.deepEqual(new Unit(5, 'cm').to('mm').toJSON(), + {'@type': 'Unit', value: 50, unit: 'mm', fixPrefix: true}); + }); + + it('fromJSON', function () { + var u1 = new Unit(5, 'cm'); + var u2 = Unit.fromJSON({'@type': 'Unit', value: 5, unit: 'cm', fixPrefix: false}); + assert.ok(u2 instanceof Unit); + assert.deepEqual(u2, u1); + + var u3 = new Unit(5, 'cm').to('mm'); + var u4 = Unit.fromJSON({'@type': 'Unit', value: 50, unit: 'mm', fixPrefix: true}); + assert.ok(u4 instanceof Unit); + assert.deepEqual(u4, u3); + }); + + }); + describe('format', function () { it('should format units with given precision', function() {