2
\$\begingroup\$

I've a string as an input which is having some specific patterns and I'm trying to parse it into a desired json. Here is my code:

const input = "status:all,applied_date:2019-04-15--to--2019-04-15,screen_status:SR|NS";

    const output = { and: {} };

    const dateSeparator = RegExp("--to--");

    function parseStr(str) {
      const arr = str.split(",");
      for (let i=0; i<arr.length; i++) {
        findPattern(arr[i]);
      }
      console.log(JSON.stringify(output));
    }

    function findPattern(subStr) {
      const subArr = subStr.split(":");
      const newKey = subArr[0].replace("_", ".");
      output["and"][newKey] = {};
      if(dateSeparator.test(subArr[1])) {
        output["and"][newKey]["between"] = subArr[1].split("--to--");
      } else if(subArr[1].split("|").length > 1) {
        output["and"][newKey]["inq"] = subArr[1].split("|");
      } else {
        output["and"][newKey]["eq"] = subArr[1];
      }
    }

    parseStr(input);

I think my approach is very naive and it's not good for complex strings(e.g. deep nesting) and also the logic I've written cannot identify if the given input conform the patterns and will fail if wrong input is provided.

Is there any efficient way to parse strings like these?

\$\endgroup\$
3
  • \$\begingroup\$ Does the current code work the way it should? \$\endgroup\$
    – Mast
    Commented Jan 26, 2020 at 8:47
  • \$\begingroup\$ To add to Mast's question, could you provide and example of the expected output? \$\endgroup\$
    – IEatBagels
    Commented Jan 28, 2020 at 21:02
  • \$\begingroup\$ @Mast It is working for the given input above but it is a specific implementation rather than a generic one which also have a downside when properties are nested. Also, the solution cannot identify if the given input conform the patterns and will fail in case of a wrong input. \$\endgroup\$
    – Abhinav
    Commented Jan 29, 2020 at 18:50

1 Answer 1

1
\$\begingroup\$

I could have criticized the most lines of the initial approach in terms of naming, relations, structuring and performance, but I believe it should be completely rewritten.


The optimized approach:

const input = "status:all,applied_date:2019-04-15--to--2019-04-15,screen_status:SR|NS";
const dateSep = /--to--/;

/**
 * Parse input string to build JSON representing 
   a rule-set of AND clauses for SQL query.
 * The return value is JSON output.
 * @param {string} str - input string
 * @param {string} [entry_sep] - entry separator, defaults to ","
 */
function strToAndClause(str, entry_sep = ",") {
    let entries = str.split(entry_sep);
    let output = { and: {} },
        and_clause = output.and;
        
    entries.forEach((entry) => {
        let [key, val] = entry.split(":"), rule = {};
        key = key.replace("_", ".");
        and_clause[key] = rule;
        
        if (dateSep.test(val)) {
            rule.between = val.split(dateSep);
        } else if (val.indexOf("|") !== -1) {
            rule.inq = val.split("|");
        } else {
            rule.eq = val;
        }
    });
    return JSON.stringify(output);
}

console.log(strToAndClause(input));

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.