2

I have a json object as below:

[
  {
    name: 'data 1',
    users: [
      {
        username: 'user 1',
        full_name: 'name 1',
        sources: [
          { type: 'type 1', name: 'source name 1' },
          { type: 'type 2', name: 'source name 2' },
        ],
      },
      {
        username: 'user 2',
        full_name: 'name 2',
        sources: [
          { type: 'type 3', name: 'source name 3' },
          { type: 'type 4', name: 'source name 4' },
        ],
      },
    ],
  },
  {
    name: 'data 2',
    users: [
      { username: 'user 3', full_name: 'name 3' },
      {
        username: 'user 4',
        full_name: 'name 4',
        sources: [
          { type: 'type 5', name: 'source name 3' },
          { type: 'type 6', name: 'source name 5' },
        ],
      },
    ],
  },
  {
    name: 'data 3',
    users: [
      { username: 'user 5', full_name: 'name 5' },
      {
        username: 'user 6',
        full_name: 'name 6',
        sources: [
          { type: 'type 5', name: 'source name 6' },
          { type: 'type 6', name: 'source name 7' },
        ],
      },
    ],
  },
];

I need a function that filter data recursively by its all values. For example when I type "data 1" it should return an array such as

[
  {
    name: 'data 1',
    users: [
      {
        username: 'user 1',
        full_name: 'name 1',
        sources: [
          { type: 'type 1', name: 'source name 1' },
          { type: 'type 2', name: 'source name 2' },
        ],
      },
      {
        username: 'user 2',
        full_name: 'name 2',
        sources: [
          { type: 'type 3', name: 'source name 3' },
          { type: 'type 4', name: 'source name 4' },
        ],
      },
    ],
  },
];

or if I type "source name 3" it should return both "data 1" and "data 2" objects as an array.

The json object may have more arrays or objects in its values. I have tried something like this but it returns all data instead of filtered data.

function search(data) {
  return data.filter((data) => {
    Object.values(data).some((value) =>
      value.constructor.name === 'Array'
        ? search(value)
        : value.constructor.name === 'Object'
        ? Object.values(value).some((innerValue) =>
            innerValue.toString().toLowerCase().includes(searchValue)
          )
        : value.toString().toLowerCase().includes(searchValue)
    );
  });
}

If I had to do that by some specific key it would be easy but I have to filter dynamically by all keys. What should I do to filter a json object like this?

2
  • So you're trying to get the all the objects {name, users, ...} that contains the object values specified? Commented Dec 4, 2021 at 19:14
  • yes exactly as you said Commented Dec 4, 2021 at 19:19

1 Answer 1

5

You could take an recursive approach. By having an object it iterates the values as well.

const
    has = value => object => Object
        .values(object)
        .some(v => v === value || v && typeof v === 'object' && has(value)(v)),
    filter = (array, value) => array.filter(has(value)),
    data = [{ name: 'data 1', users: [{ username: 'user 1', full_name: 'name 1', sources: [{ type: 'type 1', name: 'source name 1' }, { type: 'type 2', name: 'source name 2' }] }, { username: 'user 2', full_name: 'name 2', sources: [{ type: 'type 3', name: 'source name 3' }, { type: 'type 4', name: 'source name 4' }] }] }, { name: 'data 2', users: [{ username: 'user 3', full_name: 'name 3' }, { username: 'user 4', full_name: 'name 4', sources: [{ type: 'type 5', name: 'source name 3' }, { type: 'type 6', name: 'source name 5' }] }] }, { name: 'data 3', users: [{ username: 'user 5', full_name: 'name 5' }, { username: 'user 6', full_name: 'name 6', sources: [ { type: 'type 5', name: 'source name 6' }, { type: 'type 6', name: 'source name 7' }] }] }];

console.log(filter(data, 'data 1'));
console.log(filter(data, 'source name 3'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

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.