Socket
Book a DemoInstallSign in
Socket

json-expressions

Package Overview
Dependencies
Maintainers
2
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-expressions

A JavaScript expression engine for JSON-based dynamic computations and function composition

Source
npmnpm
Version
0.8.1
Version published
Weekly downloads
17
112.5%
Maintainers
2
Weekly downloads
 
Created
Source

JSON Expressions

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.

Overview

JSON Expressions is built around several key principles:

  • Serializable Logic: Express complex computations as JSON that can be stored, transmitted, and versioned
  • Deterministic: All expressions produce consistent, predictable results - no randomness or side effects
  • Composable: Build complex logic by combining simple expressions using $pipe
  • Extensible: Easily add custom expressions through packs and custom definitions
  • Safe Evaluation: Controlled execution environment without the risks of eval()
  • Type-Aware: Rich set of expressions for different data types (numbers, strings, arrays, objects)
  • Dual Execution Modes: Apply expressions to input data, or evaluate them standalone

When to Use JSON Expressions

Excellent fit for:

  • Configuration-driven applications - Store complex logic as data in databases
  • Domain experts who understand their rules - Semi-technical users comfortable with structured data (GIS analysts, statisticians, financial modelers)
  • Business rules that change frequently - Avoid code deployments for logic updates
  • Cross-platform logic sharing - Same rules run in frontend (testing) and backend (production)
  • Multi-tenant SaaS applications - Different customers need different business logic
  • Complex conditional logic - Beyond simple boolean flags but not warranting full programming languages

Poor fit for:

  • Simple boolean flags or key-value configs - Simple key/value JSON objects are completely adequate
  • Performance-critical hot paths - Direct JavaScript functions will be faster
  • Logic that rarely changes - Code deployments may be simpler

Performance Characteristics

JSON Expressions is optimized for flexibility over raw execution speed. Expect:

  • Development speed gains from eliminating deployment cycles
  • Cross-platform consistency from shared logic evaluation
  • Execution overhead compared to native JavaScript functions
  • Good performance for business rules, data transformations, and configuration logic
  • Consider caching for frequently-evaluated complex expressions

What Expressions Look Like

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:

{
  $case: {
    value: { $get: "status" },
    cases: [{ when: "active", then: { $get: "fullName" } }],
    default: "Inactive user"
  }
}

Data transformation:

{
  $pipe: [
    { $get: "children" },
    { $filterBy: { age: { $gte: 4 } } },
    { $map: { $get: "name" } },
  ];
}

Apply vs Evaluate

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
  • { $identity: null } returns the input data unchanged (identity function)
  • { $gt: 18 } tests if input data is greater than 18
  • { $filter: { $gte: 4 } } filters input array for items >= 4

evaluate(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: { "name": "Hadley" }, path: "name" } } gets property from the provided object
  • { $identity: "value" } returns "value" unchanged
  • { $gt: [25, 18] } tests if 25 > 18
  • { $sum: [1, 2, 3] } calculates sum of the provided numbers

When to use which:

  • Use apply when you have input data and want to transform, filter, or test it

    • Data processing pipelines: engine.apply(expression, userData)
    • Business rules: engine.apply(rule, customerData)
    • Validation: engine.apply(validator, formData)
  • Use evaluate when you need static calculations or have all data in the expression

    • Configuration values: engine.evaluate({ $sum: [10, 20, 30] })
    • Static computations: engine.evaluate({ $gt: [userAge, minimumAge] })
    • Template rendering: engine.evaluate({ $get: { object: config, path: "apiUrl" } })

Rule of thumb: If your expression needs external input data, use apply. If it's self-contained, use evaluate. If still in doubt, try to use the evaluate form first. If you run into a wall, you probably need to switch over to apply.

ExpressionApply ModeEvaluate Mode
$gt{ $gt: 18 }{ $gt: [25, 18] }
$get{ $get: "name" }{ $get: { object, path: "name" } }
$identity{ $identity: null }{ $identity: "value" }
$sum{ $sum: null }{ $sum: [1, 2, 3] }
$mean{ $mean: null }{ $mean: [85, 90, 88] }

Key difference: Apply mode expressions operate on the input data, while evaluate mode expressions contain all the data they need.

Mode-Specific Examples

Apply Mode - Operating on input data:

const data = { scores: [85, 90, 88], threshold: 80 };

// Get a property from input
engine.apply({ $get: "scores" }, data);
// Returns: [85, 90, 88]

// Test input against threshold
engine.apply({ $gt: 80 }, 85);
// Returns: true

// Calculate mean of input array
engine.apply({ $mean: null }, [85, 90, 88]);
// Returns: 87.67

Evaluate Mode - Self-contained expressions:

// Get property from provided object
engine.evaluate({ $get: { object: { name: "Hadley" }, path: "name" } });
// Returns: "Hadley"

// Compare two provided values
engine.evaluate({ $gt: [85, 80] });
// Returns: true

// Calculate mean of provided array
engine.evaluate({ $mean: [85, 90, 88] });
// Returns: 87.67

Common Mode Pitfalls

// Wrong: Using apply syntax in evaluate mode
engine.evaluate({ $gt: 18 }); // Error: needs comparison values

// Correct: Provide both values in evaluate mode
engine.evaluate({ $gt: [25, 18] }); // Returns: true

// Wrong: Using evaluate syntax in apply mode
engine.apply({ $gt: [25, 18] }, inputData); // Ignores inputData

// Correct: Test inputData against threshold
engine.apply({ $gt: 18 }, 25); // Returns: true

Architecture Benefits

Cross-Platform Logic Execution

The dual-mode architecture enables the same expressions to run consistently across different environments:

// Same rule logic used in multiple contexts
const eligibilityRule = {
  $matches: {
    age: { $gte: 18 },
    status: { $eq: "active" },
    balance: { $gt: 0 },
  },
};

// Frontend: Preview rule results
const previewResult = frontendEngine.apply(eligibilityRule, userData);

// Backend: Enforce rule in production
const productionResult = backendEngine.apply(eligibilityRule, userData);

// Database: Store rule for later execution
await database.saveRule("user-eligibility", eligibilityRule);

JSON Serialization Advantages

Because expressions are pure JSON, they can be:

  • Stored in databases as configuration data
  • Transmitted over HTTP for distributed evaluation
  • Versioned and audited using standard data tools and git
  • Validated with JSON Schema for correctness
  • Generated programmatically by rule builders
  • Cached and optimized by infrastructure

Expression Engine Flexibility

Different contexts can use different expression engines with tailored capabilities:

// Restrictive engine for user-facing rule builders
const userEngine = createExpressionEngine({ packs: [filtering] });

// Full-featured engine for admin interfaces
const adminEngine = createExpressionEngine({
  packs: [filtering, projection, math],
});

// Specialized engine for specific domains
const geoEngine = createExpressionEngine({
  packs: [filtering],
  custom: { $withinRadius, $intersects, $contains },
});

Production Usage

JSON Expressions powers production systems including:

  • SpectraGraph - Unified query language across multiple data sources
  • Business rules engines - Dynamic email triggers, pricing logic, access controls

Quick Start

Get up and running in 30 seconds:

import { createExpressionEngine } from "json-expressions";

// Create engine - users choose packs they need
const engine = createExpressionEngine();

// 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: { $matches: { age: { $gte: 5 } } } },
      { $map: { $get: "name" } },
    ],
  },
  children,
);
// Returns: ["Amara"]

API Reference

Core Functions

Basic Usage

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 include
  • config.custom (Object, optional) - Custom expression definitions
  • config.includeBase (Boolean, default: true) - Whether to include base expressions. Note that $literal cannot be excluded or overwritten.
import { 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,
    },
  },
});

Engine Methods

apply(expression, inputData)

Evaluates an expression against input data.

  • expression (Object) - The expression to evaluate
  • inputData (any) - The input data context for evaluation
  • Returns: Result of the expression evaluation

evaluate(expression)

Evaluates an expression without input data (for static expressions).

  • expression (Object) - The expression to evaluate
  • Returns: Static result of the expression

isExpression(value)

Tests whether a value is a valid expression.

  • value (any) - The value to test
  • Returns: Boolean indicating if the value is an expression

expressionNames

Array of all available expression names in the engine.

Error Handling

JSON Expressions provides clear error messages for common issues:

Invalid Expressions

// 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.

Type Errors

// Wrong operand type
engine.apply({ $get: 123 }, { name: "Chen" });
// Error: $get operand must be string

// 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

Data Access Errors

// 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

Best Practices

  • Use $get with defaults for safe property access: { $get: "name" }
  • Use $literal for values that might be confused with expressions
  • Test expressions with sample data before using in production
  • Use $debug (available via direct import) to inspect intermediate values in complex pipelines

Expression Packs

JSON Expressions organizes functionality into packs - curated collections of expressions for specific use cases.

Base Pack (Always Included)

The base pack contains near-universal expressions used across almost all scenarios. These expressions are included by default in every engine unless explicitly excluded.

  • $and - Logical AND operation across multiple expressions
  • $default - Returns first non-null/undefined value from array of expressions
  • $filter - Filters array items based on a condition
  • $filterBy - Filters arrays by object property conditions (combines $filter + $matches)
  • $get - Retrieves a value from data using dot notation paths with optional defaults
  • $identity - Returns input data unchanged in apply mode, or evaluates/returns the operand in evaluate mode
  • $if - Conditional expression that evaluates different branches based on a condition
  • $hasValue - Tests if a value is meaningful (not null or undefined)
  • $isEmpty - Tests if a value is empty/absent (null or undefined)
  • $exists - Tests if a property or path exists in an object
  • $literal - Returns a literal value (useful when you need to pass values that look like expressions)
  • $map - Transforms each item in an array using an expression
  • $not - Logical NOT operation that inverts a boolean expression
  • $or - Logical OR operation across multiple expressions
  • $pipe - Pipes data through multiple expressions in sequence (left-to-right)
  • $sort - Sorts arrays by property or expression with optional desc flag
  • $matches - Filters arrays using object-based property conditions (shorthand for complex filters)

Comparison expressions:

  • $eq - Tests equality using deep comparison
  • $gt - Tests if value is greater than operand
  • $gte - Tests if value is greater than or equal to operand
  • $lt - Tests if value is less than operand
  • $lte - Tests if value is less than or equal to operand
  • $ne - Tests inequality using deep comparison

Available Packs

Beyond the base pack, you can import additional functionality as needed:

import { createExpressionEngine, math, string } from "json-expressions";

const engine = createExpressionEngine({
  packs: [math, string],
});

Aggregation Pack

Statistical and aggregation functions for data analysis:

  • $count - Count of items in an array
  • $first - First item in an array
  • $last - Last item in an array
  • $max - Maximum value in an array
  • $mean - Arithmetic mean (average) of array values
  • $min - Minimum value in an array
  • $sum - Sum of array values

Array Pack

Complete array manipulation toolkit:

  • $all - Tests if all elements in an array satisfy a predicate
  • $any - Tests if any element in an array satisfies a predicate
  • $append - Appends an array to the end of another array
  • $coalesce - Returns the first non-null value from an array
  • $concat - Concatenates multiple arrays together
  • $find - Returns first element that satisfies a predicate
  • $flatMap - Maps and flattens array items
  • $flatten - Flattens nested arrays to specified depth
  • $groupBy - Groups array elements by a property or expression
  • $join - Joins array elements into a string with a separator
  • $pluck - Extracts property values from array of objects
  • $prepend - Prepends an array to the beginning of another array
  • $reverse - Returns array with elements in reverse order
  • $skip - Skips first N elements of an array
  • $take - Takes first N elements of an array
  • $unique - Returns unique values from an array

Comparison Pack

Scalar comparison operations for filtering and validation:

  • $between - Tests if value is between two bounds (inclusive)
  • $has - Tests if object has property at specified path (supports dot notation)
  • $in - Tests if value exists in an array
  • $hasValue - Tests if value is meaningful (not null or undefined)
  • $isEmpty - Tests if value is empty/absent (null or undefined)
  • $exists - Tests if property or path exists in an object
  • $nin - Tests if value does not exist in an array

Filtering Pack

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(
  {
    $matches: {
      age: { $and: [{ $gte: 2 }, { $lte: 4 }] }, // Age between 2 and 4
      status: { $eq: "active" }, // Active status
      activity: { $nin: ["napping", "sick"] }, // Not napping or sick
    },
  },
  children,
);

Logic Pack

Boolean logic and conditional operations:

  • $and - Logical AND - all expressions must be truthy
  • $case - Unified conditional expression supporting both literal comparisons and boolean predicates
  • $if - Conditional expression that evaluates different branches based on a condition
  • $not - Logical NOT - inverts the truthiness of an expression
  • $or - Logical OR - at least one expression must be truthy

Projection Pack

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" },
      { $filter: { $get: "active" } },
      {
        $map: {
          name: { $get: "name" },
          displayName: { $uppercase: { $get: "name" } },
          ageGroup: {
            $if: {
              if: { $matches: { age: { $gte: 4 } } },
              then: "Pre-K",
              else: "Toddler",
            },
          },
          activities: { $join: ", " },
        },
      },
    ],
  },
  daycareData,
);

Object Pack

Key-value manipulation and object operations:

  • $fromPairs - Creates object from array of [key, value] pairs
  • $keys - Returns array of object property names
  • $merge - Merges multiple objects together
  • $omit - Creates object excluding specified properties
  • $pairs - Returns array of [key, value] pairs from object
  • $pick - Creates object with only specified properties
  • $prop - Gets property value from object by dynamic key
  • $values - Returns array of object property values

Math Pack

Arithmetic operations and mathematical functions:

  • $abs - Absolute value of a number
  • $add - Addition operation
  • $divide - Division operation
  • $modulo - Modulo (remainder) operation
  • $multiply - Multiplication operation
  • $pow - Power/exponentiation operation
  • $sqrt - Square root operation
  • $subtract - Subtraction operation

String Pack

String processing and pattern matching:

  • $lowercase - Converts string to lowercase
  • $matchesRegex - Tests if string matches a regular expression
  • $replace - Replaces occurrences of a pattern in a string
  • $split - Splits a string into an array using a separator
  • $substring - Extracts a portion of a string
  • $trim - Removes whitespace from beginning and end of string
  • $uppercase - Converts string to uppercase

Individual Expression Imports

Some expressions are available for direct import when you need them outside of packs:

Debug Expression

The $debug expression is useful for development and troubleshooting but isn't included in any pack by default. Import it directly when needed:

import { createExpressionEngine } from "json-expressions";
import { $debug } from "json-expressions/src/definitions/flow";

const engine = createExpressionEngine({
  custom: { $debug },
});

// Use in pipelines to inspect intermediate values
const result = engine.apply(
  {
    $pipe: [
      { $get: "users" },
      { $debug: "After getting users" }, // Logs to console
      { $filter: { active: true } },
      { $debug: "After filtering active" }, // Logs to console
      { $map: { $get: "name" } },
    ],
  },
  data,
);

Any expression can be included with this method. Use it if you don't want the overhead of an entire pack.

Usage Examples

Building Blocks: Simple to Complex

JSON Expressions excel at composing simple operations into complex logic:

// Start simple: basic comparison
{
  $gt: 5;
}

// Add logic: combine conditions
{
  $and: [{ $gt: 5 }, { $lt: 10 }];
}

// Add data access: work with objects
{
  $pipe: [{ $get: "age" }, { $and: [{ $gt: 5 }, { $lt: 10 }] }];
}

// Add transformation: complex pipeline
{
  $pipe: [
    { $filter: { $gte: 4 } }, // Filter items >= 4
    { $map: { $multiply: 2 } }, // Double each value
    { $sum: null }, // Sum the results
  ];
}
// Input: [1, 2, 4, 6, 8] → Output: 36

Common Patterns

// Conditional values
{
  $if: {
    if: { $matches: { age: { $gt: 18 } } },
    then: "adult",
    else: "minor",
  }
}

// Complex filtering with multiple conditions
{
  $filter: {
    $and: [
      { $get: "active" },
      { $pipe: [{ $get: "age" }, { $gte: 18 }] },
    ]
  }
}

// Simplified filtering by object properties
{ $filterBy: { active: { $eq: true }, age: { $gte: 18 } } }

// Nested data transformation
{
  $map: {
    name: { $get: "name" },
    isEligible: { $pipe: [{ $get: "score" }, { $gte: 75 }] },
    category: {
      $case: {
        value: { $get: "age" },
        cases: [
          { when: { $lt: 13 }, then: "child" },
          { when: { $lt: 20 }, then: "teen" },
        ],
        default: "adult"
      }
    }
  }
}

Basic Data Transformation

import { createExpressionEngine } from "json-expressions";

const engine = createExpressionEngine();

const daycareData = {
  teacher: { name: "James", age: 46 },
  children: [
    { name: "Chen", age: 4, activity: "playing" },
    { name: "Serafina", age: 5, activity: "reading" },
    { name: "Diego", age: 3, activity: "napping" },
  ],
};

// Get teacher name
const teacherName = engine.apply({ $get: "teacher.name" }, daycareData);
// Returns: "James"

// Find children ready for kindergarten (age 5+)
const kindergartenReady = engine.apply(
  {
    $pipe: [
      { $get: "children" },
      { $filter: { $gte: 5 } },
      { $map: { $get: "name" } },
    ],
  },
  daycareData,
);
// Returns: ["Serafina"]

Static Calculations

// Calculate meal budget
const totalMealCost = engine.evaluate({
  $sum: [8.5, 12.75, 4.25], // breakfast, lunch, snack
});
// Returns: 25.5

Complex Business Logic

// 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"

Custom Expressions

You can extend JSON Expressions with custom functionality. For comprehensive documentation on creating custom expressions, see Custom Expressions Guide.

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"

More Examples

import { createExpressionEngine } from "json-expressions";
import { object } from "json-expressions/packs/object";

const engine = createExpressionEngine({ packs: [object] });

const students = [
  { name: "Aisha", age: 3, scores: [85, 90, 88], active: true },
  { name: "Chen", age: 5, scores: [92, 87, 95], active: true },
  { name: "Diego", age: 3, scores: [78, 84, 91], active: false },
  { name: "Serafina", age: 6, scores: [88, 92, 85], active: true },
];

// Use $filterBy for elegant filtering
const activeOlderStudents = engine.apply(
  {
    $filterBy: {
      active: { $eq: true },
      age: { $lt: 6 },
    },
  },
  students,
);
// Returns: ["Aisha", "Chen"]

// Use $pluck to extract specific fields
const studentNames = engine.apply({ $pluck: "name" }, students);
// Returns: ["Aisha", "Chen", "Diego", "Serafina"]

// Use $groupBy to organize data
const studentsByAge = engine.apply({ $groupBy: "age" }, students);
// Returns: {
//   "3": [{ name: "Aisha", age: 3, scores: [85, 90, 88], active: true }, { name: "Diego", age: 3, scores: [78, 84, 91], active: false }],
//   "5": [{ name: "Chen", age: 5, scores: [92, 87, 95], active: true }],
//   "6": [{ name: "Serafina", age: 6, scores: [88, 92, 85], active: true }]
// }

// Use $select to project/transform objects
const summaries = engine.apply(
  {
    $map: {
      $select: {
        name: { $get: "name" },
        averageScore: { $pipe: [{ $get: "scores" }, { $mean: null }] },
        isActive: { $get: "active" },
      },
    },
  },
  students,
);
// Returns: [
//   { name: "Aisha", averageScore: 87.67, isActive: true },
//   { name: "Chen", averageScore: 91.33, isActive: true },
//   ...
// ]

// Use $has to check for property existence
const hasScores = engine.apply({ $has: "scores" }, students[0]);
// Returns: true

// Use $flatten for nested arrays
const allScores = engine.apply(
  {
    $pipe: [{ $pluck: "scores" }, { $flatten: null }],
  },
  students,
);
// Returns: [85, 90, 88, 92, 87, 95, 78, 84, 91, 88, 92, 85]

// Use $unique to remove duplicates
const uniqueAges = engine.apply(
  {
    $pipe: [{ $pluck: "age" }, { $unique: null }],
  },
  students,
);
// Returns: [3, 5, 6]

TypeScript Support

JSON Expressions includes comprehensive TypeScript definitions for type safety and better developer experience.

Basic Usage

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);
}

Custom Engine Types

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(),
    },
  },
});

Expression Types

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 } }],
};

Installation

npm install json-expressions

License

MIT

Keywords

expressions

FAQs

Package last updated on 25 Sep 2025

Did you know?

Socket

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.

Install

Related posts