Build complex rules, serialize them as JSON, share them between front-end and back-end

Accessing Data


Retrieve data from the provided data object.

Most JsonLogic rules operate on data supplied at run-time. Typically this data is an object, in which case the argument to var is a property name.

Note, every operation will be demonstrated with a live example box. Feel free to edit the logic and the data and see what happens when you apply your change! Here’s what the example above would look like in JavaScript:

  { "var" : ["a"] }, // Logic
  { "a":1, "b":2 }   // Data
// 1

If you like, we support syntactic sugar to skip the array around single arguments :

You can supply a default, as the second argument, for values that might be missing in the data object. (Note, the skip-the-array sugar won’t work here because you’re passing two arguments to var):

The key passed to var can use dot-notation to get the property of a property (to any depth you need):

You can also use the var operator to access an array by numeric index:

Here’s a complex rule that mixes literals and data. The pie isn’t ready to eat unless it’s cooler than 110 degrees, and filled with apples.

You can also use var with an empty string to get the entire data object – which is really useful in map, filter, and reduce rules.


Takes an array of data keys to search for (same format as var). Returns an array of any keys that are missing from the data object, or an empty array.

Note, in JsonLogic, empty arrays are falsy. So you can use missing with if like:


Takes a minimum number of data keys that are required, and an array of keys to search for (same format as var or missing). Returns an empty array if the minimum is met, or an array of the missing keys otherwise.

This is useful if you’re using missing to track required fields, but occasionally need to require N of M fields.

Logic and Boolean Operations


The if statement typically takes 3 arguments: a condition (if), what to do if it’s true (then), and what to do if it’s false (else), like:

If can also take more than 3 arguments, and will pair up arguments like if/then elseif/then elseif/then else. Like:

See the Fizz Buzz implementation for a larger example.


Tests equality, with type coercion. Requires two arguments.


Tests strict equality. Requires two arguments.


Tests not-equal, with type coercion.


Tests strict not-equal.


Logical negation (“not”). Takes just one argument.

Note: unary operators can also take a single, non array argument:


Double negation, or “cast to a boolean.” Takes a single argument.

Note that JsonLogic has its own spec for truthy to ensure that rules will run consistently across interpreters. (e.g., empty arrays are falsy, string “0” is truthy.)


or can be used for simple boolean tests, with 1 or more arguments.

At a more sophisticated level, or returns the first truthy argument, or the last argument.


and can be used for simple boolean tests, with 1 or more arguments.

At a more sophisticated level, and returns the first falsy argument, or the last argument.

Numeric Operations

>, >=, <, and <=

Greater than:

Greater than or equal to:

Less than:

Less than or equal to:


You can use a special case of < and <= to test that one value is between two others:

Between exclusive:

Between inclusive:

This is most useful with data:

max and min

Return the maximum or minimum from a list of values.

Arithmetic, + - * /

Addition, subtraction, multiplication, and division.

Because addition and multiplication are associative, they happily take as many args as you want:

Passing just one argument to - returns its arithmetic negative (additive inverse).

Passing just one argument to + casts it to a number.


Modulo. Finds the remainder after the first argument is divided by the second argument.

This can be paired with a loop in the language that parses JsonLogic to create stripes or other effects.

In Javascript:

var rule = {"if": [{"%": [{"var":"i"}, 2]}, "odd", "even"]};
for(var i = 1; i <= 4 ; i++){
  console.log(i, jsonLogic.apply(rule, {"i":i}));
/* Outputs:
1 "odd"
2 "even"
3 "odd"
4 "even"

Array Operations

map, reduce, and filter

You can use map to perform an action on every member of an array. Note, that inside the logic being used to map, var operations are relative to the array element being worked on.

You can use filter to keep only elements of the array that pass a test. Note, that inside the logic being used to map, var operations are relative to the array element being worked on.

Also note, the returned array will have contiguous indexes starting at zero (typical for JavaScript, Python and Ruby) it will not preserve the source indexes (making it unlike PHP’s array_filter).

You can use reduce to combine all the elements in an array into a single value, like adding up a list of numbers. Note, that inside the logic being used to reduce, var operations only have access to an object like:

    "current" : // this element of the array,
    "accumulator" : // progress so far, or the initial value

all, none, and some

These operations take an array, and perform a test on each member of that array.

The most interesting part of these operations is that inside the test code, var operations are relative to the array element being tested.

It can be useful to use {"var":""} to get the entire array element within the test.

Or it can be useful to test an object based on its properties:

Note that none will return true for an empty array, while all and some will return false.


Takes one or more arrays, and merges them into one array. If arguments aren’t arrays, they get cast to arrays.

Merge can be especially useful when defining complex missing rules, like which fields are required in a document. For example, this vehicle paperwork always requires the car’s VIN, but only needs the APR and term if you’re financing.


If the second argument is an array, tests that the first argument is a member of the array:

String Operations


If the second argument is a string, tests that the first argument is a substring:


Concatenate all the supplied arguments. Note that this is not a join or implode operation, there is no “glue” string.


Get a portion of a string.

Give a positive start position to return everything beginning at that index. (Indexes of course start at zero.)

Give a negative start position to work backwards from the end of the string, then return everything.

Give a positive length to express how many characters to return.

Give a negative length to stop that many characters before the end.



Logs the first value to console, then passes it through unmodified.

This can be especially helpful when debugging a large rule.

(Check your developer console!)