TinyRuleKit

JSON Operators

Use operators after the basic rule shape is clear. They combine condition entries without moving domain behavior out of Java.

all

all passes only when every child condition passes:

JSON
{
  "all": [
    {
      "type": "LEVEL_AT_LEAST",
      "params": {
        "level": 10
      }
    },
    {
      "type": "HAS_PERMISSION",
      "params": {
        "permission": "vip"
      }
    }
  ]
}

Use it for one readable business idea. If the group needs a long explanation, create a static condition token or a reusable condition definition.

any

any passes when at least one child condition passes:

JSON
{
  "any": [
    {
      "type": "HAS_BADGE",
      "params": {
        "badge": "founder"
      }
    },
    {
      "type": "HAS_BADGE",
      "params": {
        "badge": "supporter"
      }
    }
  ]
}

Use any when the alternatives are small and reviewable.

not

not inverts one condition:

JSON
{
  "not": {
    "type": "HAS_PERMISSION",
    "params": {
      "permission": "blocked"
    }
  }
}

Prefer not for one simple child condition.

Compact Negated Static Conditions

Use !type when a static condition only exists to be negated:

JSON
{
  "!type": "HAS_PERMISSION",
  "params": {
    "permission": "blocked"
  }
}

!type is equivalent to not wrapping that static condition. Parameters are passed to the condition factory exactly like type.

Compact Negated Groups

Use !all or !any when the entire group is inverted:

JSON
{
  "!any": [
    {
      "type": "IS_BANNED"
    },
    {
      "type": "IS_SUSPENDED"
    }
  ]
}

!all is equivalent to not wrapping all. !any is equivalent to not wrapping any. They reduce one level of nesting without changing semantics.

Static Type Shorthand

Inside all, any, !all, and !any, a homogeneous list of strings can be used when every child is a static condition with no parameters:

JSON
{
  "!any": [
    "IS_BANNED",
    "IS_SUSPENDED"
  ]
}

Each string is equivalent to { "type": "..." }. This shorthand is only for advanced JSON authoring, where it improves scanability for compact sets of plain condition tokens.

Do not use it for basic rule examples, conditions with params, expressions, references, or single-child not. Do not mix strings and objects in the same operator list; mixed lists fail during loading because they are harder to read than either style on its own.

Composition Rules

  • all and any must contain at least one child condition.
  • not must contain exactly one child condition.
  • !type uses the same params shape as type.
  • !all and !any must contain at least one child condition.
  • string shorthand is allowed only as a homogeneous child list of all, any, !all, or !any.
  • A condition object should define only one condition shape: type, expr, ref, all, any, not, !all, !any, or !ref.
  • Keep nesting shallow. Deep operator trees are a sign that the concept should move to Java or to a named condition definition.

ref and !ref reference reusable condition definitions. They are introduced here only as condition shapes; they are explained in Condition Definitions.