0

I have the following issue I have a set of JSON rules like so

{
    "event": {
        "type": "maxrulecount",
        "params": {
            "maxrulecount": 2
        }
    },
    "conditions": {
        "any": [
            {
                "all": [
                    {
                        "fact": "apples",
                        "value": "20",
                        "operator": "greaterThanInclusive"
                    }
                ]
            },
            {
                "all": [
                    {
                        "fact": "bananas",
                        "value": "100",
                        "operator": "greaterThanInclusive"
                    }
                ]
            }
        ]
    }
}


So i obviously convert this to an object but the number value remains a string so I have created a function that will convert any numbers that are strings into numbers like so

checkForNumberValues(rules) {
    // allows any number of numbers together or a decimal number
    let numberRegex = /^(([0-9]{1,})|([0-9]{1,}\.[0-9]{1,}))$/g;
    // yes a loop within a loop but time complexity is no issue here
    rules?.conditions?.any?.forEach((condition) => {
      condition?.all?.forEach((rule) => {
        console.log(rule.value, numberRegex.test(rule.value)); // this is working correctly
        if (numberRegex.test(rule.value)) {
          rule.value = Number(rule.value);
        }
      });
    });
    console.log(rules);
    return rules;
}

now i can see that it is correctly identifying numbers and setting the value but when i console the result like so

console.log(checkForNumberValues(rules));

I'ts returning the rules object with the string number values instead of the number values I set..

Do I need to do something special to set nested values??

Below is an example

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' },
          { fact: 'brocolli', value: '54' },
          { fact: 'kiwi fruit', value: '199' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  let numberRegex = /^(([0-9]{1,})|([0-9]{1,}\.[0-9]{1,}))$/g;
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      if (numberRegex.test(rule.value)) {
         rule.value = Number(rule.value);
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));

Any help would be appreciated!

2
  • rules is an object and not JSON Commented Jun 4, 2020 at 5:48
  • @Andreas they start off as JSON in my db and I convert it to the rules object regardless my question is, why isnt my object updating Commented Jun 4, 2020 at 5:49

3 Answers 3

1

Regexp "remembers" the last index where a match was found when the global flag g is used (-> Why does a RegExp with global flag give wrong results?)

Use parseInt()/Number() and then test for NaN

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      const val = parseInt(rule.value);
      
      if (!isNaN(val)) {
         rule.value = val;
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));

Sign up to request clarification or add additional context in comments.

Comments

0

Use isNaN to check if the string is a number or not.

let rules = {
  conditions: {
    any: [
      {
        all: [
          { fact: 'orange', value: '70' },
          { fact: 'apple', value: '10' },
          { fact: 'brocolli', value: '54' },
          { fact: 'kiwi fruit', value: '199' }
        ]
      }
    ]
  }
}

function checkForNumberValues(rules) {
  rules.conditions.any.forEach((condition) => {
    condition.all.forEach((rule) => {
      if (!isNaN(rule.value)) {
         rule.value = Number(rule.value);
      }
    })
  });
  return rules;
}

console.log(checkForNumberValues(rules));

Comments

0

you can try a different approach

let rules = {
        conditions: {
          any: [
            {
              all: [
                { fact: 'orange', value: '70' },
                { fact: 'apple', value: '10' }
              ]
            }
          ]
        }
      }
rules.conditions.any.filter(x=>{(x.all).forEach(x=>x.value=parseInt(x.value))})
console.log(rules)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.