mathjs
mathjs copied to clipboard
toObject and fromObject
I can serialize and de-serialize an expression to JSON as shown here: https://mathjs.org/docs/core/serialization.html
In my application the expression is part of a bigger JSON which is de-serialized at a higher level. I would need to de-serialize an expression from an object like this:
const node = math.parse('age >= 21 ? 999 + 5 : 111 + 2')
const objectExpression = node.toObject();
const node2 = math.fromObject(objectExpression)
Of course I could do something like this but it's not optimal because I would have to serialize the object to JSON first:
const node = math.parse('age >= 21 ? 999 + 5 : 111 + 2')
const json = JSON.stringify(node);
const expression = JSON.parse(json, math.revive);
Is there a way to do this without calling the revive function recursively? I tried to use map-keys-deep but the reviver gets called for a parent leaf and then for the child and it seems that the order need to be reversed to use the revive function.
I have been able to do it this way using deepdash:
console.log('tree', tree);
const restoredNode = mapDeep(tree, (value, key, object, info) => {
if (info.afterIterate) {
return math.reviver(key, value);
}
return value;
}, {
callbackAfterIterate: true,
});
console.log('node', restoredNode);
Which prints:
tree {
mathjs: 'OperatorNode',
op: '+',
fn: 'add',
args: [
{ mathjs: 'SymbolNode', name: 'age' },
{ mathjs: 'ConstantNode', value: 21 }
],
implicit: false
}
node Node {
implicit: false,
op: '+',
fn: 'add',
args: [ Node { name: 'age' }, Node { value: 21 } ]
}
It would be nice if the library would support this natively.
I get what you mean. That's interesting. You want to turn mathjs objects into plain JSON objects (non-stringified).
A simple (not very efficient) solution is to do it like this:
function toObject(mathjsObject) {
return JSON.parse(JSON.stringify(mathjsObject))
}
function fromObject(jsonObject) {
return JSON.parse(JSON.stringify(jsonObject), math.json.reviver)
}
I suppose your "higher level serialization" is not customizable in such a way that it can embrace the provided reviver
? I think that would be even better. Your proposed solution is to first turn mathjs objects into JSON objects, and next serialize these JSON objects. That's still two steps, still not optimal. Can you explain a bit more about your use case Aalex?
@josdejong I receive JSON messages from an MQ broker. The MQ library automatically de-serializes messages and passes them to a handler function. Somewhere deep inside the handler function math.js is called with a part of the whole object to evaluate an expression.
The message contains multiple dynamic properties which are math.js expressions and are evaluated for a given context (scope).
Thanks for the context Aalex, that makes sense.
I think your idea of fromObject
and toObject
is indeed worth implementing. It will give another powerful option for serialization/deserialization like your use case, and I expect it will be not that much code.
Anyone interested in implementing fromObject
and toObject
?
Funny: https://www.bram.us/2019/11/25/faster-javascript-apps-with-json-parse/
I don't think it will apply to our case here, but it could be a good idea to do some real world benchmarking :)
@josdejong I think I'm in need of this functionality, would you be opposed to a PR implementing it?
Thanks Matt, a PR would be very welcome, I see your draft in #2774