Skip to main content

Python library designed for evaluating data against serializable JSON criteria

Project description

json-criteria

json-criteria is a lightweight, dependency-free Python library designed for evaluating data against serializable JSON criteria. It offers a variety of built-in operators, supports custom operators, and can handle complex nested conditions, making it a valuable and flexible tool for condition-based decision-making.

Why use json-criteria?

  • Serialization to JSON
    • The criteria used by json-criteria can be easily serialized to JSON format. This enables the persistence of criteria, making it suitable for storage in databases or external configurations.
  • Dynamic Criteria Adjustment
    • Since the criteria is stored as JSON, it allows for dynamic adjustments without the need for code deployment. Criteria can be modified or extended as needed, providing the ability to adapt application behavior without code changes.
  • Flexibility and Maintainability
    • Storing conditions in a serializable format enhances application flexibility and maintainability. Criteria can be fine-tuned, added, or removed independently of the application code, resulting in a more adaptable and easier-to-maintain system.
  • Dependency-Free
    • json-criteria is intentionally designed to be lightweight and dependency-free, ensuring ease of integration into diverse projects without introducing unnecessary dependencies.

In summary, json-criteria empowers developers with a versatile and lightweight solution for handling criteria, fostering a more dynamic, adaptable, and maintainable approach to decision-making in applications.

Examples

Simple Condition

Evaluate a single condition:

from json_criteria import meets_criteria

# Define a record and criteria
record = {'name': 'Joe', 'age': 30}
criteria = {'key': 'age', 'op': 'equal_to', 'value': 30}

# Check if the record meets the criteria
# `result` will be True
result = meets_criteria(record, criteria)

Nested Conditions

Handle more complex scenarios with nested conditions:

from json_criteria import meets_criteria

# Define a record
record = {
    'name': 'Alice',
    'age': 28,
    'department': 'Engineering',
    'experience_years': 5,
    'is_manager': False
}

# criteria:
# (age >= 25 AND experience_years >= 3) OR (department is 'Engineering' AND is_manager is True)
criteria = {
    'OR': [
        {'AND': [
            {'key': 'age', 'op': 'greater_than_or_equal_to', 'value': 25},
            {'key': 'experience_years', 'op': 'greater_than_or_equal_to', 'value': 3}
        ]},
        {'AND': [
            {'key': 'department', 'op': 'equals', 'value': 'Engineering'},
            {'key': 'is_manager', 'op': 'equals', 'value': True}
        ]}
    ]
}

# Check if the record meets the criteria
# `result` will be True
result = meets_criteria(record, criteria)

Simple Custom Operator

Pass in a Config object to specify custom operators.

from json_criteria import meets_criteria, Config

def custom1(record_value, value):
    return record_value + value == 60

record = { 'name': 'Joe', 'age': 30 }
criteria = { 'key': 'age', 'op': 'custom1', 'value': 30 }
config = Config(custom_ops = { 'custom1': custom1 })

# `result` will be True
result = meets_criteria(record, criteria, config)

These examples demonstrate the simplicity and flexibility of json_criteria in handling both basic and intricate conditions for evaluating data. The library's support for nested conditions enables the representation of complex logical structures, making it a valuable tool for decision-making in various scenarios.

Criteria

Criteria in json-criteria are represented as dictionaries, specifying the conditions that record(s) must satisfy. This allows for flexible and expressive criteria, supporting both simple conditions and intricate logical structures with AND, OR, and NOT operators.

A condition is composed of three fundamental components:

  • key: The key to be evaluated.
  • op: The operator indicating the comparison type.
  • value: The expected value for the specified key.

Additional keys, such as id and description, can be included without impacting functionality. This feature provides the flexibility to add context or relevant information to the criteria.

Built-In Operators:

  • equal_to
  • not_equal_to
  • greater_than
  • less_than
  • greater_than_or_equal_to
  • less_than_or_equal_to
  • in
  • not_in
  • contains
  • not_contains
  • starts_with
  • not_starts_with
  • ends_with
  • not_ends_with
  • matches_regex

These operators provide a comprehensive set of comparisons to handle a wide range of conditions in your criteria.

API

Below you will find documentation for each library function, including examples.

all_meet_criteria

Determine if all records in a given list meet the specified criteria. This function evaluates whether all records in the provided list satisfy the specified criteria, providing a straightforward way to ensure that the entire dataset meets the required conditions.

from json_criteria import all_meet_criteria

# Define a list of user records
user_records = [
    {'name': 'Alice', 'age': 28, 'department': 'Engineering', 'is_manager': False},
    {'name': 'Bob', 'age': 35, 'department': 'Marketing', 'is_manager': True},
    {'name': 'Charlie', 'age': 45, 'department': 'Sales', 'is_manager': False}
]

# criteria: age >= 25 AND (is_manager is True OR department is 'Engineering')
criteria = {
    'AND': [
        {'key': 'age', 'op': 'greater_than_or_equal_to', 'value': 25},
        {'OR': [
            {'key': 'is_manager', 'op': 'equals', 'value': True},
            {'key': 'department', 'op': 'equals', 'value': 'Engineering'}
        ]}
    ]
}

# Check if all user records meet the criteria
# `result` will be True
result = all_meet_criteria(user_records, criteria)

any_meet_criteria

This function determines whether any record in the provided list satisfies the specified criteria, offering a convenient way to identify if at least one record meets the required conditions.

from json_criteria import any_meet_criteria

# Define a list of employee records and a criteria
employee_records = [
    {'name': 'Alice', 'age': 32, 'department': 'Sales'},
    {'name': 'Bob', 'age': 45, 'department': 'Marketing'},
    {'name': 'Charlie', 'age': 28, 'department': 'Engineering'},
    {'name': 'David', 'age': 37, 'department': 'Sales'},
]

# criteria: age greater than 35 OR (department is 'Engineering' AND age is less than 30)
criteria = {
    'OR': [
        {'key': 'age', 'op': 'greater_than', 'value': 35},
        {'AND': [
            {'key': 'department', 'op': 'equal_to', 'value': 'Engineering'},
            {'key': 'age', 'op': 'less_than', 'value': 30}
        ]}
    ]
}

# Check if any employee record meets the criteria
# `result` will be True
result = any_meet_criteria(employee_records, criteria)

apply_using_criteria

Apply a specified function to each record that meets the given criteria. This function allows for targeted and conditional transformations on a list of records, enhancing flexibility in data manipulation.

from json_criteria import apply_using_criteria

# Define a list of user records and a criteria
user_records = [
    {'name': 'Joe', 'age': 30, 'department': 'Sales'},
    {'name': 'John', 'age': 60, 'department': 'Marketing'},
    {'name': 'Alice', 'age': 25, 'department': 'Engineering'},
]

# criteria: Apply the function to records where age is less than 40 AND belong to the 'Engineering' department
criteria = {
    'AND': [
        {'key': 'age', 'op': 'less_than', 'value': 40},
        {'key': 'department', 'op': 'equal_to', 'value': 'Engineering'}
    ]
}

# Define a function to apply (e.g., mark users as active)
def mark_as_active(record):
    record['is_active'] = True
    return record

# Apply the specified function to records meeting the criteria
# `result` will be:
# [{'name': 'Joe', 'age': 30, 'department': 'Sales'},
#  {'name': 'John', 'age': 60, 'department': 'Marketing'},
#  {'name': 'Alice', 'age': 25, 'department': 'Engineering', 'is_active': True}]
result = apply_using_criteria(user_records, criteria, mark_as_active)

combine_criteria

Combine multiple criteria using the AND or OR operator. This function allows for the composition of more complex logical conditions by nesting individual criteria within a larger structure.

from json_criteria import combine_criteria

# Define two individual criteria
criteria1 = {
    'AND': [
        {'key': 'name', 'op': 'starts_with', 'value': 'S'},
        {'key': 'age', 'op': 'equal_to', 'value': 100}
    ]
}

criteria2 = {
    'OR': [
        {'key': 'name', 'op': 'starts_with', 'value': 'L'},
        {'key': 'age', 'op': 'equal_to', 'value': 20}
    ]
}

# Combine criteria using the AND operator
# `result` will be:
# {
#     'AND': [
#         { 'AND': [
#             { 'key': 'name', 'op': 'starts_with', 'value': 'S' }, 
#             { 'key': 'age', 'op': 'equal_to', 'value': 100 }
#             ] 
#         },
#         { 'OR': [
#             { 'key': 'name', 'op': 'starts_with', 'value': 'L' }, 
#             { 'key': 'age', 'op': 'equal_to', 'value': 20 }
#             ]
#         }
#     ]
# }
result = combine_criteria('AND', [criteria1, criteria2])

filter_using_criteria

Filter a list of records based on the given criteria. This function provides a mechanism for selectively extracting records that meet specific conditions, enhancing the flexibility of data filtering.

from json_criteria import filter_using_criteria

# Define a list of employee records
employee_records = [
    {'name': 'Alice', 'age': 28, 'department': 'Engineering', 'is_manager': False},
    {'name': 'Bob', 'age': 35, 'department': 'Marketing', 'is_manager': True},
    {'name': 'Charlie', 'age': 45, 'department': 'Sales', 'is_manager': False},
    {'name': 'Susan', 'age': 30, 'department': 'Engineering', 'is_manager': True}
]

# criteria: (age >= 30 AND is_manager is True) OR (department is 'Engineering' AND name starts with 'S')
criteria = {
    'OR': [
        {'AND': [
            {'key': 'age', 'op': 'greater_than_or_equal_to', 'value': 30},
            {'key': 'is_manager', 'op': 'equals', 'value': True}
        ]},
        {'AND': [
            {'key': 'department', 'op': 'equals', 'value': 'Engineering'},
            {'key': 'name', 'op': 'starts_with', 'value': 'S'}
        ]}
    ]
}

# Filter employee records based on the criteria
# `result` will be: [
#    {'name': 'Bob', 'age': 35, 'department': 'Marketing', 'is_manager': True},
#    {'name': 'Susan', 'age': 30, 'department': 'Engineering', 'is_manager': True}
# ]
result = filter_using_criteria(employee_records, criteria)

find_using_criteria

Find the first record that meets the given criteria. Returns None if none is found. This function provides a convenient way to locate the initial occurrence of a record satisfying specific conditions within a list.

from json_criteria import find_using_criteria

# Define a list of employee records
employee_records = [
    {'name': 'Alice', 'age': 28, 'department': 'Engineering', 'is_manager': False},
    {'name': 'Bob', 'age': 35, 'department': 'Marketing', 'is_manager': True},
    {'name': 'Charlie', 'age': 45, 'department': 'Sales', 'is_manager': False},
    {'name': 'Susan', 'age': 30, 'department': 'Engineering', 'is_manager': True}
]

# criteria: Find the first employee who is a manager and older than 30
criteria = {'AND': [
    {'key': 'is_manager', 'op': 'equals', 'value': True},
    {'key': 'age', 'op': 'greater_than', 'value': 30}
]}

# Find the first employee record meeting the criteria
# `result` will be: {'name': 'Bob', 'age': 35, 'department': 'Marketing', 'is_manager': True}
result = find_using_criteria(employee_records, criteria)

get_all_criteria

Given a record and a list of criteria, get all criteria that the record meets. This function is useful for analyzing and identifying the specific criteria that a record satisfies within a given list.

from json_criteria import get_all_criteria

# Define a user
user = {
    'name': 'Alice',
    'age': 28,
    'interests': ['Technology', 'Books'],
    'purchased_products': ['Laptop']
}

# criteria list:
criteria_list = [
    # User has an interest in 'Technology' AND (User is older than 25 OR User has purchased a 'Laptop')
    {'id': 10, 'AND': [
        {'key': 'interests', 'op': 'contains', 'value': 'Technology'},
        {'OR': [
            {'key': 'age', 'op': 'greater_than', 'value': 25},
            {'key': 'purchased_products', 'op': 'contains', 'value': 'Laptop'}
        ]}
    ]},
    # User has an interest in 'Books' AND User has not purchased a 'Tablet'
    {'id': 11, 'AND': [
        {'key': 'interests', 'op': 'contains', 'value': 'Books'},
        {'key': 'purchased_products', 'op': 'not_contains', 'value': 'Tablet'}
    ]}
]

# Get all criteria that the user meets
# `result` will be:
# [{'id': 10, 'AND': [
#     {'key': 'interests', 'op': 'contains', 'value': 'Technology'},
#     {'OR': [
#         {'key': 'age', 'op': 'greater_than', 'value': 25},
#         {'key': 'purchased_products', 'op': 'contains', 'value': 'Laptop'}
#     ]}
# ]}]
result = get_all_criteria(user, criteria_list)

meets_criteria

Determine if a record meets the given criteria. This function provides a flexible and expressive way to evaluate whether a record satisfies specified conditions, supporting a variety of operators for comprehensive criteria checks.

from json_criteria import meets_criteria

# Define a record for a user
user_record = {
    'user_type': 1,
    'email': 'test@email.com',
    'is_active': True,
    'age': 30,
    'department': 'Engineering'
}

# Criteria Description:
# - User type is 1
# - AND (Email ends with '@email.com' OR (Is active AND Age is less than 40))
# - AND (Department is 'Engineering' AND (Is active OR Age is greater than or equal to 30))
# - AND (User type is not 2 AND Email does not end with '@test.com')
criteria = {
    'AND': [
        {'key': 'user_type', 'op': 'equal_to', 'value': 1},
        {'OR': [
            {'key': 'email', 'op': 'ends_with', 'value': '@email.com'},
            {'AND': [
                {'key': 'is_active', 'op': 'equal_to', 'value': True},
                {'key': 'age', 'op': 'less_than', 'value': 40}
            ]}
        ]},
        {'AND': [
            {'key': 'department', 'op': 'equal_to', 'value': 'Engineering'},
            {'OR': [
                {'key': 'is_active', 'op': 'equal_to', 'value': True},
                {'key': 'age', 'op': 'greater_than_or_equal_to', 'value': 30}
            ]}
        ]},
        {'AND': [
            {'key': 'user_type', 'op': 'not_equal_to', 'value': 2},
            {'key': 'email', 'op': 'not_ends_with', 'value': '@test.com'}
        ]}
    ]
}

# Check if the user record meets the specified criteria
# `result` will be True
result = meets_criteria(user_record, criteria)

Configuration

Configuring json-criteria is optional. By default, the library works without any additional setup. However, if you want to customize the behavior, such as adding custom operators, you can create a Config object and pass it to the library function being called. Available configuration options are detailed below.

custom_ops

This option allows you to define custom operators. To use it, provide a dictionary where the keys are the operator names, and the values are the corresponding operator functions. Each operator function receives two arguments:

  1. record_value: The value from the data record.
  2. value: The value specified in the criteria.
from json_criteria import Config

def same_len(record_value, value):
    return len(record_value) == len(value)

config = Config(custom_ops = { 'same_len': same_len })

Contributing Guide

I welcome all pull requests. Please make sure you add appropriate test cases for any features added.

To run tests: python3 -m unittest

To lint: pylint src

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

json_criteria-0.2.0.tar.gz (11.9 kB view details)

Uploaded Source

Built Distribution

json_criteria-0.2.0-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file json_criteria-0.2.0.tar.gz.

File metadata

  • Download URL: json_criteria-0.2.0.tar.gz
  • Upload date:
  • Size: 11.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.12

File hashes

Hashes for json_criteria-0.2.0.tar.gz
Algorithm Hash digest
SHA256 14ef0aa5b006e3818028af4b870f920c25f1a6c5184b7eb8b83ddcbad340c0fb
MD5 0d25506270bd2e55b87fd4bd953ebae3
BLAKE2b-256 cf11a3bc61a23cef9d4109500f1870787a2d3da92f8ee700e67ff2214c50c0cf

See more details on using hashes here.

File details

Details for the file json_criteria-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for json_criteria-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b3c8335543b56164b4eae57c3eab132abbde14a93c96dcb2fef3cb8a445a7ccf
MD5 62afa6d6fa77a30183e05b129af55694
BLAKE2b-256 ccdbb0bc785f48d94f83f423af98db2ce2b0831724c34f731967fd81d0709ed8

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page