1

My goal is to tell the JSON.parse function with the optional reviver argument that I would like it if the string being passed to the calc(string) function has a key named "expr" to perform the operation inside of that expression, and then continue to work outwards to operate on the rest of the string.

Every time I run this I am getting NaN.

If I comment out the two last calc(string) calls before console.log(initNumber) then the program runs as expected.

So if the key is "expr" and the value of the nested "op" key is "add" then perform the add() function on that nested object. Same goes for if the "op" key is "subtract".

Any help is immensely appreciated.

var initNum = 0;

var calc = function(string) {
    var calcString = JSON.parse(string, reviver);

    add(calcString);
    subtract(calcString);
};

var add = function(string) {
    if (string["op"] == "add") {
    var numString = parseInt(JSON.stringify(string["number"]));
    initNum = numString + initNum;
    return initNum;
  }
}
var subtract = function(string) {
    if (string["op"] == "subtract") {
    var numString = parseInt(JSON.stringify(string["number"]));
    initNum = initNum - numString;
    return initNum;
  }
}

var reviver = function(key, val) {
  if (key == "expr") {
    if (val.op == "add") {
      return add(val);
    }
    else if (val.op == "subtract") {
      return subtract(val);
    }
  }
    else {
      return val;
    }
};

calc('{"op" : "add", "number" : 5}');
calc('{"op" : "subtract", "number" : 2}');
calc('{"op" : "add", "number" : 19}');
calc('{"op": "subtract", "expr" : {"op" : "add", "number" : 15}}');
calc('{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}');
console.log(initNum);
giggidy
  • 75
  • 1
  • 1
  • 8

1 Answers1

1

A few points :

  • reviver will give you the already parsed values, you don't need to parse them again.
  • if you convert an expr into a value, your add and subtract functions need to be able to read those values, and not just number - I think, maybe you intend for different logic. That's why I get operand the way I do below. Either way, you need to be aware that there might not be a number argument, and handle that.
  • the reason you were getting NaN is because of the above- you were trying to get the number from objects which didn't have one(the results of reviving exprs), which gives you undefined which broke the calculations.

Basically, remember that

{"op": "subtract", "expr" : {"op" : "add", "number" : 15}}

goes to

{"op": "subtract", "expr" : 37}

after you revive the expression, so you need to handle that.

var initNum = 0;

var calc = function(string) {
    var calcObj = JSON.parse(string, reviver);

    add(calcObj);
    subtract(calcObj);
};

var add = function(obj) {
    if (obj["op"] == "add") {
      var operand = (obj["number"])? obj["number"] : obj["expr"];
      initNum = operand + initNum;
      console.log("running total : "+initNum);
      return initNum;
  }
}
var subtract = function(obj) {
    if (obj["op"] == "subtract") {
      var operand = (obj["number"])? obj["number"] : obj["expr"];
      initNum = initNum - operand;
      console.log("running total : "+initNum);
      return initNum;
  }
}

var reviver = function(key, val) {
  if (key == "expr") {
    if (val.op == "add") {
      return add(val);
    }
    else if (val.op == "subtract") {
      return subtract(val);
    }
  }
    else {
      return val;
    }
};

calc('{"op" : "add", "number" : 5}');
calc('{"op" : "subtract", "number" : 2}');
calc('{"op" : "add", "number" : 19}');
calc('{"op": "subtract", "expr" : {"op" : "add", "number" : 15}}');
calc('{"op": "add", "expr" : {"op" : "add", "expr" : {"op" : "subtract", "number" : 3}}}');
console.log(initNum);
Karl Reid
  • 2,147
  • 1
  • 10
  • 16
  • thank you so much. That makes wayyyyyyy more sense now. So in the var operand part, you're now saying that "If the JSON object has a "number" key, use that, otherwise use the "expr" key." Thank you thank you. – giggidy Oct 22 '17 at 01:10
  • `If the JSON object has a "number" key, use that, otherwise use the "expr" key` Yes, exactly. And because `reviver` is [defined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter) to work 'beginning with the most nested properties and proceeding to the original value itself', all `expr`s should be already converted to their values by the time they are seen by the `add` or `subtract` operation surrounding them. – Karl Reid Oct 22 '17 at 01:14
  • Just brilliant. Makes total sense. :) – giggidy Oct 22 '17 at 01:18