gentooboontoo / js-quantities

JavaScript library for quantity calculation and unit conversion
http://gentooboontoo.github.io/js-quantities/
MIT License
396 stars 102 forks source link

Suggestion: toJSON() transport option #70

Open WorldMaker opened 8 years ago

WorldMaker commented 8 years ago

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.

vsmalladi commented 8 years ago

I agree this would be nice.

luzlab commented 7 years ago

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?"

gentooboontoo commented 7 years ago

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.

luzlab commented 7 years ago

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 commented 7 years ago

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 commented 6 years ago

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