js-quantities icon indicating copy to clipboard operation
js-quantities copied to clipboard

Suggestion: toJSON() transport option

Open WorldMaker opened this issue 9 years ago • 6 comments

To persist a Qty object to a JSON store or pass to a JSON REST service it looks like you can rely on Qty#toString() roundtripping. However, it might be useful to have a Qty#toJSON() method (and a constructor/factory to match) that can serialize a richer data structure and potentially avoid some of the string generation and parsing steps.

WorldMaker avatar Jul 28 '16 19:07 WorldMaker

I agree this would be nice.

vsmalladi avatar Jul 28 '16 20:07 vsmalladi

yes! This would be a much appreciated feature! Is it challenging?

Honestly, I'm just checking this library out for the first time. We're about to bake unit handling into our web app and I'm looking to pick one library to get started... I thought js-quanties was the best - are there any other that support math operations? The big question I had was "Can I serialize and deserialize Qty objects from JSON?"

luzlab avatar Dec 15 '16 20:12 luzlab

I am open to any suggestion or help about concrete implementation. To me, the best representation of a quantity is its plain string form (as output by Qty#toString()). In this case, Qty#toJSON would just be implemented as a call to Qty#toString() with no arguments. It is also possible to the client code to add a customized JSON serialization by simply extending Qty.prototype.

For now, I don't see any use case for a richer data structure except for performance reasons as suggested by @WorldMaker but it might eventually be considered with further argumentation.

gentooboontoo avatar Dec 15 '16 22:12 gentooboontoo

Yeah, I realized that I could use toString() to serialize and deserialize Qty objects after my last post. I made an atmosphere package to use js-quantities in a Meteor app. Basically, I just had to add a few methods (.toJSONValue(), .typeName(), .clone(), and .eq()) to support automatic handling of Qty object between the client and server.

I was looking over the code for the constructor and saw the option to import from a DefinitionObject. Is a definition object just the following? If so, I could just export this from .toJSONValue() rather than .toString().

{
   scalar : Number;
   numerator: [ String ],
   denominator: [ String ]
}

luzlab avatar Dec 20 '16 16:12 luzlab

So I made a fork that automatically detects if EJSON is being used and adds support for automatic detection/serialization/deserialization of Qty objects.

var ejson = require('ejson');
var qty = require('js-quantities');
var m = qty('1 m');
var stringified = ejson.stringify({foo: m}) // {"foo":{"$type":"js-quantity","$value":{"scalar":1,"numerator":["<meter>"],"denominator":["<1>"]}}}
var parsed = ejson.parse(stringified);
console.log(parsed.foo.toString()) // 1 m

I had to make changes to the build config to support this and I haven't added any tests.

If there's interest in this, I can submit a PR.

luzlab avatar Aug 09 '17 20:08 luzlab

I created an npm module ejson-extras that extends EJSON to support automatic serialization and deserialization of Qty objects.

luzlab avatar Dec 01 '17 03:12 luzlab