0

I'm working on an existing project that takes query parameters in an oddly formatted string dot notation. But they must be converted into objects before processing. This is currently being performed with conditionals on specific keys by name.

How can this be performed dynamically? Below you will find an example of the input and desired output.

Input:

{ 
    date.gte: '2019-01-01', 
    date.lt: '2020-01-01' 
}

Output:

{
    date: {
        gte: '2019-01-01',
        lt: '2020-01-01'
    }
}
3
  • 1
    What have you tried, and what exactly is the problem with it? Which part specifically have you had an issue with? Commented Dec 17, 2019 at 19:43
  • I attempted an implementation using Object.keys(obj).forEach(function(key) { } where I would attempt see if key included a period and if so key,split('.') . Then take those results and return them. Just was not sure if that was an efficient or proper path. Commented Dec 17, 2019 at 19:49
  • Please give a minimal reproducible example then. What efficiency is needed? What would "proper" mean? Commented Dec 17, 2019 at 19:50

3 Answers 3

4

You could use reduce and split methods to split each key into array and build nested structure based on that array.

const data = {
  'date.gte': '2019-01-01',
  'date.lt': '2020-01-01'
}

const result = Object.entries(data).reduce((r, [k, v]) => {
  k.split('.').reduce((a, e, i, ar) => {
    return a[e] || (a[e] = ar[i + 1] ? {} : v)
  }, r)

  return r;
}, {})

console.log(result)

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

Comments

1

By you saying "oddly formatted string dot notation" I assume you mean "date.gte" & "date.lt"

const input = {
    "date.gte": "2019-01-01",
    "date.lt": "2020-01-01"
};

const res = Object.keys(input).reduce(
    (result, current) => {
        const [, operator] = current.split(".");

        result.date[operator] = input[current];

        return result;
    },
    { date: {} }
);

console.log(res);

3 Comments

fails for: const input = { "date.gte.a": "2019-01-01", "date.lt.b": "2020-01-01" };
@ssBarBee the question did not mention about that random input.
he said: This is currently being performed with conditionals on specific keys by name. - I would assume that they have weird inputs :D
1

Here's an improvement on Dan's answer that doesn't rely on knowing the key-value pairs in the original object. As much as Nenad's answer blows this out of the water, I worked for too long on this to not post it :)

const formatter = (weirdObject, s = '.') => Object.keys(weirdObject).reduce((acc, cur) => {
  const [parent, child] = cur.split(s);
  if (!acc[parent]) acc[parent] = {};
  acc[parent][child] = weirdObject[cur];
  return acc;
}, {});

// -- Demonstration:

const input1 = {
  "date.gte": "2019-01-01",
  "date.lt": "2020-01-01"
};

const input2 = {
  "person:name": "Matt",
  "person:age": 19
};

const res1 = formatter(input1);
const res2 = formatter(input2, ':');

console.log(res1);
console.log(res2);

1 Comment

nice! its defiantly more readable than the top voted answer :)

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.