JSON Query Builder: Rule Format, MongoDB & React UI
Last updated:
Overview
JSON query builders are UI components that allow non-technical users to construct complex filters without writing code. This guide covers designing rule/filter JSON formats (group-based with AND/OR logic), translating to backend query languages (MongoDB, SQL, Elasticsearch), implementing recursive React components, validating rule syntax, and comparing open-source libraries.
Key Patterns
- Group-Based Rules: JSON structure with "condition" logic (AND/OR) and nested rules
- Field + Operator + Value: Each rule is [field, operator, value] — where operator is eq, ne, lt, gt, in, like, regex, etc.
- Recursive Groups: Groups can contain other groups for complex nested conditions
- Backend Translation: Convert JSON rules to MongoDB queries, SQL WHERE clauses, or Elasticsearch filters
- React Components: Group editor (buttons to add/remove rules), field selector dropdown, operator selector, value input
- Immutable Updates: Store rules as JSON, create new state objects on changes (not mutations)
Best Practices
- Define rule structure clearly: every rule must have field, operator, and value with type validation
- Use a separate enum or configuration file for allowed fields and operators — prevents injection and ensures consistency
- Implement recursive rule validation before sending to backend — catch user errors early
- For operators, define which ones apply to which field types (date fields get lt/gt, strings get like/regex, numbers get eq/ne/lt/gt)
- Translate JSON rules on the backend, not the frontend — frontend translation can be bypassed
- Support rule presets (saved filters) by storing rules in the database with a name and description
- Use TypeScript to type the rule structure and ensure consistency at compile time
- For complex nested rules, provide a visual representation (tree view or indented text) so users understand the logic
- Implement "simplified query mode" for common use cases (name contains, created after date) alongside advanced builder
- Test rule generation with edge cases (null values, special characters, very long strings)
Rule Format Design
A minimal rule structure includes: a group with logic (AND or OR), an array of child rules, and each rule with field, operator, and value. Example: A group with logic="AND" containing rules for (name contains "alice") AND (created_at after 2026-01-01). Recursive groups enable: (name contains "alice" OR email contains "alice") AND (created_at after 2026-01-01).
Field Configuration
Define which fields users can filter on and which operators apply to each. A configuration array should list: field name (displayed to user), backend field name (sent to API), field type (string, number, date, boolean, enum), applicable operators (eq, ne, lt, gt, in, like, regex), and optional helper text. This configuration drives both the frontend UI (which fields appear in the dropdown) and backend validation (reject queries with invalid field/operator combinations).
Operator Definitions
Operators vary by field type. Strings: eq (equals), ne (not equals), like (contains substring, case-insensitive), regex (pattern match). Numbers: eq, ne, lt, lte, gt, gte, in (multiple values). Dates: eq, ne, lt, lte, gt, gte, between. Booleans: eq only. Enums: eq, ne, in. Define operators globally so translation logic is consistent.
Translating to MongoDB Queries
Convert rule JSON to MongoDB query syntax. A rule with field "name", operator "like", value "alice" becomes a regex query. A group with logic "AND" combines conditions with the and operator. OR groups combine with the or operator. Translate recursively for nested groups. Validate on the backend to prevent injection.
Translating to SQL
Convert rule JSON to SQL WHERE clause. A rule with field "name", operator "like", value "alice" becomes LOWER(name) LIKE LOWER('%alice%'). A group with logic "AND" becomes (condition1 AND condition2). Use parameterized queries (prepared statements) to prevent SQL injection. Never concatenate user input directly into the query string.
React Component Architecture
Implement a RuleBuilder component that recursively renders groups and rules. Each group has buttons to add rules or add subgroups. Each rule has dropdowns for field and operator, an input for value, and a delete button. Use controlled components with onChange callbacks to update state. Store rules as JSON state, allowing users to export or save filters.
Validation
Validate rules at multiple stages: on the frontend (immediate user feedback), on the backend (prevent invalid queries). Frontend validation checks: every rule has a field, operator, and value; value matches the field type; operators are allowed for the field. Backend validation repeats these checks and additionally checks: field and operator combinations are allowed; value length and format constraints are met; query doesn't exceed complexity limits (max group depth, max rule count).
Libraries
React Query Builder: Popular React component library with drag-and-drop, material-ui styling, built-in validation
JSONLogic: Lightweight format for expressing conditional logic as JSON, can be executed on both frontend and backend
FusionCharts QueryBuilder: Commercial component with advanced features like rule presets and SQL export
FilterBuilder (from ag-grid): Filter UI integrated with data grid component
Export and Presets
Allow users to save filters as presets — store the rule JSON with a name and description in the database. When a user clicks "Use this filter", load the saved rules back into the builder or apply them directly. This enables reuse of complex filters across the application.
Further reading and primary sources
- React Query Builder — React component for building dynamic filter queries with drag-and-drop
- JSONLogic Documentation — Lightweight JSON-based conditional logic that runs on multiple platforms
- MongoDB Query Language — MongoDB query operators reference for translating rules
- SQL WHERE Clause — SQL WHERE syntax and operators for translating rules to SQL
- Elasticsearch Query DSL — Elasticsearch query syntax for filter translation