{"id":20597727,"url":"https://github.com/triggerdotdev/json-hero-query","last_synced_at":"2025-09-26T14:52:19.540Z","repository":{"id":57122536,"uuid":"432172775","full_name":"triggerdotdev/json-hero-query","owner":"triggerdotdev","description":"An easy way of querying for objects inside JSON","archived":false,"fork":false,"pushed_at":"2021-12-17T12:17:35.000Z","size":212,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-19T03:55:48.534Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/triggerdotdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-26T12:34:21.000Z","updated_at":"2023-12-15T17:19:42.000Z","dependencies_parsed_at":"2022-08-24T14:59:29.916Z","dependency_job_id":null,"html_url":"https://github.com/triggerdotdev/json-hero-query","commit_stats":null,"previous_names":["jsonhero-io/json-hero-query"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/triggerdotdev/json-hero-query","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triggerdotdev%2Fjson-hero-query","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triggerdotdev%2Fjson-hero-query/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triggerdotdev%2Fjson-hero-query/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triggerdotdev%2Fjson-hero-query/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/triggerdotdev","download_url":"https://codeload.github.com/triggerdotdev/json-hero-query/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triggerdotdev%2Fjson-hero-query/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277095771,"owners_count":25760027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-26T02:00:09.010Z","response_time":78,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T08:23:41.013Z","updated_at":"2025-09-26T14:52:19.502Z","avatar_url":"https://github.com/triggerdotdev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JSON Hero Query\nA TypeScript/JavaScript library that provides a simple way of accessing objects inside JSON using paths with filtering\n\n## How to install\n`npm install @jsonhero/query`\n\n## Getting started\n### Importing\nYou can require\n```js\nconst { JSONHeroQuery } = require('@jsonhero/query');\n```\n\nOr if you're using TypeScript:\n```ts\nimport { JSONHeroQuery } from '@jsonhero/query';\n```\n\n### Sample object\nGiven the following JSON variable called `employees`\n```js\nlet employees = {\n    people: [\n        {\n            name: 'Matt',\n            age: 36,\n            favouriteThings: ['Monzo', 'The Wirecutter', 'Jurassic Park', 'Rocket League'],\n        },\n        {\n          name: 'James',\n          age: 39,\n          favouriteThings: ['Far Cry 1', 'Far Cry 2', 'Far Cry 3'],\n        },\n        {\n          name: 'Eric',\n          age: 38,\n          favouriteThings: ['Bitcoin', 'Rocket League'],\n        },\n        {\n          name: 'Dan',\n          age: 34,\n          favouriteThings: ['Frasier'],\n        },\n    ],\n    count: 4\n}\n```\n\n### Anatomy of a query\nTo construct a query you provide an object with an array of paths (with optional filters):\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'operator',\n        key: 'age',\n        operatorType: '\u003e=',\n        value: 36,\n      },\n    ],\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results is an array with the Matt, James and Eric objects in\n```\n\n### Filter types\nThere are three types of filters, these can be selected by using the `type` field\n\n| Filter name   | What it does\n| ---           | ---          \n| `operator`    | Allows you to perform logical operators tests on the current object\n| `subPath`     | Allows you to perform logical operator tests on the current object or any sub-objects using a path\n| `or`          | Allows you to add sub-filters where if any of the sub-filters pass, this filter will pass\n| `and`         | Allows you to add `and` conditions inside an `or`. The top-level `filters` is `and` already\n\n### Operator filter and operator types\nThe `operator` filter type applies the specified test to each object at that path.\n\nIf the object fails the test then it will be excluded from the results.\n\nThere are several familiar operator types you can use. These can also all be used in the `subPath` filter type.\n\n| Operator name         | What it does\n| ---                   | ---          \n| `==`                  | Performs `==` on object and specified value. (not strict equality)\n| `!=`                  | Performs `!=` on object and specified value. (not strict inequality)\n| `\u003e`                   | Performs `\u003e` on object and specified value \n| `\u003e=`                  | Performs `\u003e=` on object and specified value\n| `\u003c`                   | Performs `\u003c` on object and specified value\n| `\u003c=`                  | Performs `\u003c=` on object and specified value\n| `startsWith`          | Non-strings will fail this test. Performs string.startsWith(value);\n| `endsWith`            | Non-strings will fail this test. Performs string.endsWith(value);\n| `containsValue`       | For objects and arrays, will check if they contain the specified value\n| `isEmpty`             | If null, undefined, empty array or empty object this is true\n| `isNotEmpty`          | if not null, not undefined, not empty array or not empty object this is true\n\nAnother example, specifying a `key` and using `startsWith` \n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'operator',\n        key: 'name',\n        operatorType: 'startsWith',\n        value: 'Jam',\n      },\n    ],\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results is an array with just the James object in\n```\n\nA query that doesn't use `key`, which means it applies the filter to the object at the current path (not a value at the specified sub-key)\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*'\n  },\n  {\n    path: 'name',\n    filters: [\n      {\n        type: 'operator',\n        operatorType: '!=',\n        value: 'Matt',\n      },\n    ],\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results = ['James', 'Eric', 'Dan']\n//note that this is just an array of strings, not objects, because we are specifying name in the path\n```\n\n### Sub-path queries\nThese queries allow you to do advanced filtering. You can specify a path to any sub-object from the current path and then apply filters to determine if the current object should be included or not.\n\nIn this query we eliminate any people where one of their favourite things isn't Rocket League, then return their name.\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'subPath',\n        path: 'favouriteThings.*',\n        operatorType: '==',\n        value: 'Rocket League',\n      },\n    ],\n  },\n  {\n    path: 'name',\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results = ['Matt', 'Eric']\n```\n\n### Or queries\nSimply put, these allow you to combine filters and have an object pass the test if any of the sub-filters pass.\n\nThis query is using subPath queries (similar to the one above) but in this case if any of them pass we will include the person.\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'or',\n        subFilters: [\n          {\n            type: 'subPath',\n            path: 'favouriteThings.*',\n            operatorType: '==',\n            value: 'Rocket League',\n          },\n          {\n            type: 'subPath',\n            path: 'favouriteThings.*',\n            operatorType: '==',\n            value: 'Monzo',\n          },\n          {\n            type: 'subPath',\n            path: 'favouriteThings.*',\n            operatorType: '==',\n            value: 'Frasier',\n          },\n        ],\n      },\n    ],\n  },\n  {\n    path: 'name',\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results = ['Matt', 'Eric', 'Dan']\n```\n\n### And queries\nThe top-level `filters` objects are `and` filters. If you need to test an `and` inside an `or` filter, you can easily do that:\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'or',\n        subFilters: [\n          {\n            type: 'and',\n            subFilters: [\n              {\n                type: 'subPath',\n                path: 'favouriteThings.*',\n                operatorType: '==',\n                value: 'Rocket League',\n              },\n              {\n                type: 'subPath',\n                path: 'favouriteThings.*',\n                operatorType: '==',\n                value: 'Monzo',\n              },\n            ],\n          },\n          {\n            type: 'and',\n            subFilters: [\n              {\n                type: 'subPath',\n                path: 'favouriteThings.*',\n                operatorType: '==',\n                value: 'Bitcoin',\n              },\n              {\n                type: 'subPath',\n                path: 'favouriteThings.*',\n                operatorType: '==',\n                value: 'Rocket League',\n              },\n            ],\n          },\n        ],\n      },\n    ],\n  },\n  {\n    path: 'name',\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees); \n//results = ['Matt', 'Eric']\n```\n\n### Getting paths as well as the results\nYou can get the path objects as well as the values by passing an optional object when you query\n\n```js\nlet queryConfig = [\n  {\n    path: 'people',\n  },\n  {\n    path: '*',\n    filters: [\n      {\n        type: 'subPath',\n        path: 'favouriteThings.*',\n        operatorType: 'startsWith',\n        value: 'Far Cry',\n      },\n    ],\n  },\n  {\n    path: 'name',\n  },\n];\n\nlet query = new JSONHeroQuery(queryConfig);\nlet results = query.all(employees, { includePath: true});\n//results will be an object like this \n//{\n//  value: 'James',\n//  path: a JSONHeroPath for this element\n//}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftriggerdotdev%2Fjson-hero-query","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftriggerdotdev%2Fjson-hero-query","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftriggerdotdev%2Fjson-hero-query/lists"}