
Security News
Deno 2.6 + Socket: Supply Chain Defense In Your CLI
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.
json-expressions
Advanced tools
A JavaScript expression engine for JSON-based dynamic computations and function composition
A powerful JavaScript expression engine for JSON-based dynamic computations and function composition. JSON Expressions provides a declarative syntax for creating complex logic, transformations, and calculations that can be serialized, stored, and executed safely.
Perfect for configuration-driven applications, business rules engines, and anywhere you need dynamic logic represented as data.
JSON Expressions is built around several key principles:
$pipeeval()Expressions are JSON objects that describe computations to be performed. Each expression has a single key that identifies the expression type (prefixed with $) and a value that provides the parameters:
Simple comparison:
{ "$gt": 18 }
Logical expressions:
{ "$and": [
{ "$gte": 18 },
{ "$lt": 65 }
]}
Conditional logic:
{ "$if": {
"if": { "$eq": "active" },
"then": { "$get": "fullName" },
"else": "Inactive User"
}}
Data transformation:
{ "$pipe": [
{ "$get": "children" },
{ "$filter": { "$gte": 4 } },
{ "$map": { "$get": "name" } }
]}
JSON Expressions provides two distinct execution modes that serve different purposes:
apply(expression, inputData)Applies the expression to input data. The expression acts like a function that receives the input data and transforms or tests it.
import { createExpressionEngine } from "json-expressions";
// Create an engine (users choose their own packs)
const engine = createExpressionEngine();
// Expression: "is the input greater than 18?"
const expression = { $gt: 18 };
const inputData = 25;
const result = engine.apply(expression, inputData);
// Returns: true (because 25 > 18)
In apply mode, expressions receive the input data as context and operate on it:
{ $get: "name" } gets the "name" property from input data{ $gt: 18 } tests if input data is greater than 18{ $filter: { $gte: 4 } } filters input array for items >= 4evaluate(expression)Evaluates the expression independently without input data. The expression is fully self-contained and produces a static result.
// Expression: "what is the sum of these numbers?"
const expression = { $sum: [1, 2, 3, 4] };
const result = engine.evaluate(expression);
// Returns: 10 (static calculation)
In evaluate mode, expressions contain all the data they need:
{ $get: { object: data, path: "name" } } gets property from the provided object{ $gt: [25, 18] } tests if 25 > 18{ $sum: [1, 2, 3] } calculates sum of the provided numbersWhen to use which:
Get up and running in 30 seconds:
import { createExpressionEngine } from "json-expressions";
// Create engine - users choose packs they need
const engine = createExpressionEngine();
// Simple data filtering
const children = [
{ name: "Chen", age: 3 },
{ name: "Amara", age: 5 },
{ name: "Diego", age: 4 }
];
// Find school-age children (5+)
const schoolAge = engine.apply(
{
$pipe: [
{ $filter: { $gte: 5 } },
{ $map: { $get: "name" } }
]
},
children
);
// Returns: ["Amara"]
Users create engines with the packs they need:
import { createExpressionEngine } from "json-expressions";
const engine = createExpressionEngine(); // Includes base pack by default
const result = engine.apply(expression, data);
const staticResult = engine.evaluate(expression);
createExpressionEngine(config)Creates a custom expression engine with specified configuration.
Parameters:
config.packs (Array, optional) - Array of expression pack objects to includeconfig.custom (Object, optional) - Custom expression definitionsconfig.includeBase (Boolean, default: true) - Whether to include base expressionsimport { createExpressionEngine } from "json-expressions";
import { math } from "json-expressions/packs/math";
// Create engine with math pack
const mathEngine = createExpressionEngine({
packs: [math]
});
// Create engine with only custom expressions (no base pack)
const customEngine = createExpressionEngine({
includeBase: false,
custom: {
$double: {
apply: (operand, inputData) => inputData * 2,
evaluate: (operand) => operand * 2
}
}
});
apply(expression, inputData)Evaluates an expression against input data.
evaluate(expression)Evaluates an expression without input data (for static expressions).
isExpression(value)Tests whether a value is a valid expression.
expressionNamesArray of all available expression names in the engine.
JSON Expressions provides clear error messages for common issues:
// Unknown expression
engine.apply({ $unknown: 5 }, 10);
// Error: Unknown expression operator: "$unknown". Did you mean "$not"?
// Values that look like expressions but aren't
engine.apply({ $notAnExpression: 5 }, 10);
// Error: Unknown expression operator: "$notAnExpression". Use { $literal: {"$notAnExpression": 5} } if you meant this as a literal value.
// Wrong operand type
engine.apply({ $get: 123 }, { name: "Chen" });
// Error: $get operand must be string or object with {path, default?}
// Boolean predicates must return boolean values
engine.apply({ $case: { value: 5, cases: [{ when: { $literal: "not boolean" }, then: "result" }] } });
// Works fine - literal comparison: 5 === "not boolean" → false, continues to default
// Strict property access on null/undefined
engine.apply({ $prop: "name" }, null);
// Error: Cannot read properties of null (reading 'name')
// Missing required properties
engine.evaluate({ $get: { path: "name" } });
// Error: $get evaluate form requires 'object' and 'path' properties
$get with defaults for safe property access: { $get: { path: "name", default: "Unknown" } }$literal for values that might be confused with expressions$debug to inspect intermediate values in complex pipelinesJSON Expressions includes comprehensive TypeScript definitions for type safety and better developer experience.
import { createExpressionEngine, Expression } from "json-expressions";
const engine = createExpressionEngine();
// Type-safe expression definition
const expression: Expression = { $gt: 18 };
// Apply with typed input and output
const result: unknown = engine.apply(expression, 25);
// Type guards for expressions
if (engine.isExpression(someValue)) {
// someValue is now typed as Expression
const result = engine.apply(someValue, data);
}
import { createExpressionEngine, ExpressionEngine } from "json-expressions";
// Create typed engine
const engine: ExpressionEngine = createExpressionEngine({
custom: {
$myExpression: {
apply: (operand: string, inputData: any) => inputData + operand,
evaluate: (operand: string) => operand.toUpperCase()
}
}
});
The library provides specific interfaces for each expression type:
import {
GetExpression,
PipeExpression,
FilterExpression
} from "json-expressions";
const getExpr: GetExpression = { $get: "name" };
const pipeExpr: PipeExpression = {
$pipe: [
{ $get: "children" },
{ $filter: { $gte: 5 } }
]
};
JSON Expressions organizes functionality into packs - curated collections of expressions for specific use cases.
The base pack contains near-universal expressions used across almost all scenarios. These expressions are included by default in every engine unless explicitly excluded.
Comparison expressions:
Beyond the base pack, you can import additional functionality as needed:
import { createExpressionEngine } from "json-expressions";
import { math } from "json-expressions/packs/math";
import { string } from "json-expressions/packs/string";
const engine = createExpressionEngine({
packs: [math, string]
});
Statistical and aggregation functions for data analysis:
Complete array manipulation toolkit:
Scalar comparison operations for filtering and validation:
Complete toolkit for WHERE clause logic and data filtering - combines field access, comparisons, logic, and pattern matching:
Perfect for building complex filters with a single import:
import { createExpressionEngine, filtering } from "json-expressions";
const engine = createExpressionEngine({ packs: [filtering] });
// Complex daycare filtering
const activeToddlers = engine.apply({
$and: [
{ $gte: 2 }, // Age >= 2
{ $lt: 4 }, // Age < 4
{ $get: "active" }, // Active status
{ $nin: ["napping", "sick"] } // Not napping or sick
]
}, children);
Boolean logic and conditional operations:
Complete toolkit for SELECT clause operations and data transformation - combines aggregation, array operations, string transforms, and conditionals:
Perfect for transforming and projecting data with a single import:
import { createExpressionEngine, projection } from "json-expressions";
const engine = createExpressionEngine({ packs: [projection] });
// Complex daycare reporting
const report = engine.apply({
$pipe: [
{ $get: "children" },
{ $map: {
name: { $get: "name" },
displayName: { $uppercase: { $get: "name" } },
ageGroup: { $if: {
if: { $gte: 4 },
then: "Pre-K",
else: "Toddler"
}},
activities: { $join: ", " }
}},
{ $filter: { $get: "active" } }
]
}, daycareData);
Arithmetic operations and mathematical functions:
String processing and pattern matching:
Temporal functions for date/time operations:
Some expressions don't belong to any specific pack but are available when imported individually:
These expressions must be imported individually or used in custom engine configurations:
import { createExpressionEngine } from "json-expressions";
import { $uuid } from "json-expressions";
// Create engine with standalone expressions
const engine = createExpressionEngine({
custom: { $uuid }
});
// Generate a unique identifier
const id = engine.evaluate({ $uuid: null });
// Returns: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
import { createExpressionEngine } from "json-expressions";
const engine = createExpressionEngine();
const daycareData = {
teacher: { name: "Amara", age: 28 },
children: [
{ name: "Chen", age: 4, activity: "playing" },
{ name: "Fatima", age: 5, activity: "reading" },
{ name: "Diego", age: 3, activity: "napping" }
]
};
// Get teacher name with default
const teacherName = engine.apply(
{ $get: { path: "name", default: "Unknown" } },
daycareData.teacher
);
// Returns: "Amara"
// Find children ready for kindergarten (age 5+)
const kindergartenReady = engine.apply(
{
$pipe: [
{ $get: "children" },
{ $filter: { $gte: 5 } },
{ $map: { $get: "name" } }
]
},
daycareData
);
// Returns: ["Fatima"]
// Calculate meal budget
const totalMealCost = engine.evaluate({
$sum: [8.50, 12.75, 4.25] // breakfast, lunch, snack
});
// Returns: 25.5
// Generate unique session ID
const sessionId = engine.evaluate({ $uuid: null });
// Returns: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
// Age-based activity recommendations with mixed literal and expression conditions
const activityRecommendation = engine.apply(
{
$case: {
value: { $get: "age" },
cases: [
{ when: 2, then: "Sensory play and simple puzzles" }, // Literal comparison
{ when: 3, then: "Art activities and story time" }, // Literal comparison
{ when: { $eq: 4 }, then: "Pre-writing skills and group games" }, // Expression predicate
{ when: { $gte: 5 }, then: "Early math and reading readiness" } // Expression predicate
],
default: "Age-appropriate developmental activities"
}
},
{ age: 4 }
);
// Returns: "Pre-writing skills and group games"
You can easily extend JSON Expressions with custom functionality:
import { createExpressionEngine } from "json-expressions";
const customEngine = createExpressionEngine({
custom: {
// Custom validation
$isValidEmail: {
apply: (operand, inputData) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(inputData);
},
evaluate: (operand) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(operand);
}
},
// Custom transformation
$titleCase: {
apply: (operand, inputData) => {
return inputData.toLowerCase()
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
},
evaluate: (operand) => {
return operand.toLowerCase()
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
}
}
});
// Use custom expressions
const isValid = customEngine.apply({ $isValidEmail: null }, "user@example.com");
// Returns: true
const formatted = customEngine.evaluate({ $titleCase: "john doe" });
// Returns: "John Doe"
npm install json-expressions
MIT
Contributions are welcome! Please feel free to submit issues and pull requests.
FAQs
A JavaScript expression engine for JSON-based dynamic computations and function composition
The npm package json-expressions receives a total of 9 weekly downloads. As such, json-expressions popularity was classified as not popular.
We found that json-expressions demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.