🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis
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

latest
Source
npmnpm
Version
0.15.0
Version published
Weekly downloads
5
-84.85%
Maintainers
2
Weekly downloads
 
Created
Source

JSON Expressions

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

Well-suited for configuration-driven applications, business rules engines, and anywhere you need dynamic logic represented as data.

Quick Start

npm install json-expressions
import {
  createExpressionEngine,
  mathPack,
  comparisonPack,
} from "json-expressions";

// Create an engine with the packs you need
const engine = createExpressionEngine({ packs: [mathPack, comparisonPack] });

// Apply expressions to your data
const user = { age: 25, score: 85 };

// Simple comparisons
engine.apply({ $gt: 18 }, user.age); // true (25 > 18)

// Complex logic with input data
engine.apply(
  {
    $matchesAll: {
      age: { $gte: 18 },
      score: { $gt: 80 },
    },
  },
  user,
); // true

What Are JSON Expressions?

JSON Expressions let you write logic as JSON that operates on input data. Each expression has a key starting with $ and describes what operation to perform:

// "Is the input greater than 18?"
{
  $gt: 18;
}

// "Get the 'name' property from input"
{
  $get: "name";
}

// "Filter input array for items with age >= 18"
{
  $filterBy: {
    age: {
      $gte: 18;
    }
  }
}

Extensible by Design

Create custom expressions for your domain:

const engine = createExpressionEngine({
  custom: {
    $isValidEmail: (operand, inputData) =>
      /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(inputData),
  },
});

engine.apply({ $isValidEmail: null }, "user@example.com"); // true

Read more about creating custom expressions.

Bundle Size & Tree-Shaking

JSON Expressions is optimized for tree-shaking when using ESM imports. Import only the packs you need for optimal bundle sizes:

Use CaseBundle SizeGzipped
Math pack only31 KB7 KB
Math + Array packs36 KB8 KB
All packs except temporal42 KB9 KB
With temporal (date/time)133 KB23 KB

How it works:

// Import packs (recommended) - Modern bundlers tree-shake automatically
import { mathPack, createExpressionEngine } from "json-expressions";

const engine = createExpressionEngine({ packs: [mathPack] });
// Result: ~31 KB in your bundle (only math + engine)

// Import individual expressions for even smaller bundles
import {
  $add,
  $multiply,
  $sum,
  createExpressionEngine,
} from "json-expressions";

const customPack = { $add, $multiply, $sum };
const engine = createExpressionEngine({ packs: [customPack] });
// Result: ~28 KB in your bundle (only selected expressions + engine)

Requirements:

  • Modern bundler (Webpack 5+, Vite, Rollup, esbuild)
  • ESM imports (import, not require)

Node.js with require(): Uses pre-built bundle (~71 KB with external dependencies). For smaller server bundles, use ESM imports in Node 16+.

Design Philosophy

JSON Expressions prioritizes flexibility over raw performance. This library is designed for scenarios where dynamic, data-driven logic is more valuable than execution speed. Performance is an important design goal to enable as many uses as possible, but it will never be a replacement for performance tuned code.

Why JSON Expressions?

Appropriate for:

  • Configuration-driven applications - Store complex logic as data in databases
  • Business rules that change frequently - Avoid code deployments for logic updates
  • Multi-tenant SaaS applications - Different customers need different business logic
  • Cross-platform logic sharing - Same rules run in frontend and backend

When NOT to Use JSON Expressions

  • High-frequency operations (more than 100k ops/sec requirements)
  • Real-time systems with strict latency requirements
  • Simple static logic that doesn't need to change
  • Performance-critical hot paths

Features:

  • Serializable Logic: Express complex computations as JSON that can be stored and transmitted
  • Safe Evaluation: Controlled execution environment without the risks of eval()
  • Composable: Build complex logic by combining simple expressions
  • Extensible: Add custom expressions through packs and custom definitions

Limitations:

  • Performance and Memory Overhead: Interpretation layer adds execution cost compared to native JavaScript
  • Synchronous Evaluation: Expressions return values immediately and cannot perform async operations like API calls or database queries

Data Handling

JSON Expressions distinguishes between two types of errors:

  • Configuration errors (malformed expressions) - These throw errors immediately
  • Data variance (null, undefined, or unexpected types) - These return sensible defaults

This design handles real-world heterogeneous data gracefully:

// String operations return null for non-string input
engine.apply({ $uppercase: null }, null); // null (not an error)
engine.apply({ $uppercase: null }, 123); // null (not an error)

// Array operations return empty arrays for non-array input
engine.apply({ $filterBy: { age: { $gt: 5 } } }, null); // []

// Object operations return empty objects/arrays for non-object input
engine.apply({ $keys: null }, null); // []

// Predicates return false for type mismatches
engine.apply({ $matchesRegex: "\\d+" }, null); // false
engine.apply({ $exists: "field" }, "not an object"); // false

In databases and APIs, fields often have nullable types (string | null). Expressions can operate on this data without requiring null checks at every step, making them more composable and easier to use in query builders and data pipelines.

Null and undefined are treated identically throughout the library, following JSON semantics where both represent the absence of a value.

Common Patterns

Data Access and Transformation

const order = {
  items: [{ price: 10 }, { price: 15 }],
  tax: 0.08,
};

// Get nested data
engine.apply({ $get: "items" }, order);
// Returns: [{ price: 10 }, { price: 15 }]

// Transform arrays
engine.apply(
  {
    $pipe: [{ $get: "items" }, { $map: { $get: "price" } }, { $sum: null }],
  },
  order,
);
// Returns: 25 (sum of all prices)

Conditional Logic

const user = { status: "premium", age: 25 };

// Simple conditions
engine.apply(
  {
    $if: {
      if: { $eq: [{ $get: "status" }, "premium"] },
      then: "VIP Access",
      else: "Standard Access",
    },
  },
  user,
);
// Returns: "VIP Access"

// Complex case statements
engine.apply(
  {
    $case: {
      value: { $get: "status" },
      cases: [
        { when: "premium", then: "Gold Badge" },
        { when: "standard", then: "Silver Badge" },
      ],
      default: "No Badge",
    },
  },
  user,
);
// Returns: "Gold Badge"

Filtering and Validation

const children = [
  { name: "Ximena", age: 4, active: true },
  { name: "Yousef", age: 5, active: false },
  { name: "Zoë", age: 6, active: true },
];

// Filter with complex conditions
engine.apply(
  {
    $filter: {
      $and: [{ $get: "active" }, { $gte: [{ $get: "age" }, 5] }],
    },
  },
  children,
);
// Returns: [{ name: "Zoë", age: 6, active: true }]

Validating Expressions

Before evaluating expressions, validate them to catch invalid operators:

const engine = createExpressionEngine();

// Get all validation errors (empty array = valid)
const errors = engine.validateExpression({ $get: "name" });
if (errors.length === 0) {
  // Safe to evaluate
}

// Multiple errors returned at once
const errors = engine.validateExpression({
  $pipe: [{ $bad1: "oops" }, { $bad2: "another" }],
});
// errors.length === 2

// Or ensure validity, throwing all errors
try {
  engine.ensureValidExpression({ $typo: "bad" });
} catch (err) {
  console.log(err.message);
  // Unknown expression operator: "$typo". Did you mean "$gt"?
}

Both methods perform deep validation of nested expressions and correctly handle $literal operands.

Available Expression Packs

Import only the functionality you need:

import {
  createExpressionEngine,
  mathPack, // $add, $subtract, $multiply, $divide, $sum, $mean, etc.
  comparisonPack, // $eq, $ne, $gt, $lt, $gte, $lte, $in, $nin
  arrayPack, // $filter, $map, $sort, $unique, $flatten, $groupBy
  objectPack, // $pick, $omit, $merge, $keys, $values, $pairs
  stringPack, // $concat, $join, $matchesRegex
  filteringPack, // $filterBy, $find, $all, $any
  projectionPack, // $select, $pluck
  aggregationPack, // Statistical functions
  temporalPack, // $addDays, $formatDate, $diffDays, $isAfter, etc.
} from "json-expressions";

const engine = createExpressionEngine({
  packs: [mathPack, comparisonPack, arrayPack],
});

→ Complete Pack Reference - Detailed guide to all packs and their expressions

Documentation

Performance

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

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

Benchmark Results

Performance varies based on operation complexity:

Operation TypePerformanceExample
Simple operations1-1.6M ops/sec$gt, $get, $add
Complex operations300-700K ops/sec$matchesAll, $filter
Nested data access2.4M ops/sec$get: "user.profile.name"
Data processing70-300K ops/secPipeline transformations
Large datasets (1000 items)1.6-3.9K ops/secFiltering, grouping

Run npm run bench for detailed performance metrics on your hardware.

Well suited for configuration logic, business rules, and data processing. Consider direct JavaScript functions for performance-critical hot paths.

Keywords

expressions

FAQs

Package last updated on 22 Nov 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