What is jora?
Jora is a powerful query language for JavaScript objects, allowing you to perform complex queries and transformations on JSON-like data structures. It is particularly useful for data manipulation, filtering, and aggregation.
What are jora's main functionalities?
Basic Querying
This feature allows you to extract specific fields from an array of objects. In this example, it extracts the 'name' field from each object in the array.
const jora = require('jora');
const data = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }];
const result = jora('name')(data);
console.log(result); // ['Alice', 'Bob']
Filtering
This feature allows you to filter objects based on certain conditions. In this example, it filters out objects where the 'age' field is greater than 25.
const jora = require('jora');
const data = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }];
const result = jora('[age > 25]')(data);
console.log(result); // [{ name: 'Alice', age: 30 }]
Aggregation
This feature allows you to perform aggregation operations on fields. In this example, it calculates the sum of the 'age' field across all objects.
const jora = require('jora');
const data = [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }];
const result = jora('age.sum()')(data);
console.log(result); // 55
Nested Queries
This feature allows you to perform queries on nested structures. In this example, it extracts the 'name' field from each object within the 'users' array.
const jora = require('jora');
const data = { users: [{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }] };
const result = jora('users[name]')(data);
console.log(result); // ['Alice', 'Bob']
Other packages similar to jora
lodash
Lodash is a popular utility library that provides a wide range of functions for manipulating arrays, objects, and other data structures. While it does not offer a query language like Jora, it provides similar functionalities through its collection of utility functions.
json-query
Json-query is a lightweight library for querying JSON data. It offers a simpler syntax compared to Jora but is less powerful in terms of the complexity of queries it can handle.
jq
Jq is a command-line tool for processing JSON data. It offers a powerful query language similar to Jora but is designed to be used in a command-line environment rather than within JavaScript code.
Jora
JavaScript object query language, and a library to process and perform Jora queries on data.
STATUS: Jora is stable, but syntax may change in next releases. Still very much work in progress (ideas and thoughts).
Features:
- Tolerant to data stucture queries (e.g. just returns nothing for paths that not reachable)
- Compact syntax for common tasks
- Aggregate values across arrays and eliminate duplicates by default
- Stat collecting mode (powers suggestions)
- Tolerant parsing mode (useful to provide suggestions for query in an editor)
- Extensible DSL on query build by custom method list
Related projects:
Table of content:
Query syntax overview
Jora is a query language designed for JSON-like data structures. It extends JSON5 and shares many similarities with JavaScript.
See Docs & playground.
Expressions
Jora expressions are the building blocks of Jora queries. Expressions can include comments, literals, operators, functions, and variables.
Literals
Jora supports literals, which include:
- Numbers:
42
, -3.14
, 6.022e23
- Strings:
"hello"
, 'world'
, `template${yes}`
, "\u{1F600}"
- Booleans:
true
, false
- Regular expressions:
/regexp/flags
- Object literals:
{ hello: 'world' }
(see Object literals) - Array literals:
[1, 2, 3]
(see Array literals) - Functions:
=> …
(see Functions) - Keywords:
NaN
, Infinity
, null
and undefined
See Literals
Operators
Jora supports most JavaScript operators, including:
- Arithmetic:
+
, -
, *
, /
, %
- Comparison:
=
, !=
, <
, <=
, >
, >=
, ~=
- Logical:
and
, or
, not
(alias no
), ??
, is
, in
, not in
, has
, has no
- Ternary:
?:
- Grouing:
( )
- Pipeline:
|
See Operators
Dot, bracket and slice notations
Jora provides notations for accessing properties and elements: dot, bracket and slice notations. Dot notation is similar to JavaScript's property access notation, using a period followed by the property name (e.g., $.propertyName
). Bracket notation encloses the property name or index within square brackets (e.g., $['propertyName']
or $[0]
), it's also possible to use functions to choose. Slice notation provides a concise syntax to slice elements with optional step (array[5:10:2]
selects each odd element from 5th to 10th indecies).
Methods and functions
Jora provides a rich set of built-in methods for manipulating data, such as map()
, filter()
, group()
, sort()
, reduce()
, and many others. You can also define custom functions using the =>
arrow function syntax, and use them as a method.
Mapping and filtering
Jora has a concise syntax for mapping and filtering. The map(fn)
method is equivalent to .(fn())
, while the filter(fn)
method is equivalent to .[fn()]
.
Variables
Variables in Jora are helpful for storing intermediate results or simplifying complex expressions. To define a variable, use the $variableName: expression;
syntax.
See Variables
NPM package
Install & import
Install with npm:
npm install jora
Basic usage:
import jora from 'jora';
const jora = require('jora');
Bundles are available for use in a browser:
dist/jora.js
– minified IIFE with jora
as global
<script src="node_modules/jora/dist/jora.js"></script>
<script>
jora('query')(data, context);
</script>
dist/jora.esm.js
– minified ES module
<script type="module">
import jora from 'node_modules/jora/dist/jora.esm.js'
</script>
By default (for short path) a ESM version is exposing. For IIFE version a full path to a bundle should be specified. One of CDN services like unpkg
or jsDelivr
can be used:
-
jsDeliver
<script type="module">
import jora from 'https://cdn.jsdelivr.net/npm/jora';
</script>
<script src="https://cdn.jsdelivr.net/npm/jora/dist/jora.js"></script>
-
unpkg
<script type="module">
import jora from 'https://unpkg.com/jora';
</script>
<script src="https://unpkg.com/jora/dist/jora.js"></script>
API
import jora from 'jora';
const query = jora('foo.bar');
const result = query(data, context);
See the details in Jora library API
Quick demo
Get npm dependency paths (as a tree) that have packages with more than one version:
import jora from 'jora';
import { exec } from 'child_process';
function printTree() {
}
exec('npm ls --all --json', (error, stdout) => {
if (error) {
return;
}
const npmTree = JSON.parse(stdout);
const depsPathsToMultipleVersionPackages = jora(`
$normalizedDeps: => dependencies.entries().({ name: key, ...value });
$multiVersionPackages:
..$normalizedDeps()
.group(=>name, =>version)
.({ name: key, versions: value.sort() })
.[versions.size() > 1];
$pathToMultiVersionPackages: => .($name; {
name,
version,
otherVersions: $multiVersionPackages[=>name=$name].versions - version,
dependencies: $normalizedDeps()
.$pathToMultiVersionPackages()
.[name in $multiVersionPackages.name or dependencies]
});
$pathToMultiVersionPackages()
`)(npmTree);
printTree(depsPathsToMultipleVersionPackages);
});
Example of output:
jora@1.0.0
├─ c8@7.11.0
│ ├─ istanbul-lib-report@3.0.0
│ │ └─ supports-color@7.2.0 [more versions: 8.1.1]
│ ├─ test-exclude@6.0.0
│ │ └─ minimatch@3.1.2 [more versions: 3.0.4]
│ ├─ v8-to-istanbul@8.1.1
│ │ └─ convert-source-map@1.8.0
│ │ └─ safe-buffer@5.1.2 [more versions: 5.2.1]
│ ├─ yargs-parser@20.2.9 [more versions: 20.2.4]
│ └─ yargs@16.2.0
│ └─ yargs-parser@20.2.9 [more versions: 20.2.4]
├─ eslint@8.10.0
│ ├─ @eslint/eslintrc@1.2.0
│ │ ├─ ignore@4.0.6 [more versions: 5.2.0]
│ │ └─ minimatch@3.1.2 [more versions: 3.0.4]
...
See more examples in Complex Jora query examples