json-remap-engine 0.3.0
JSONPath-driven remapping engine that produces JSON Patch operations.
License: MIT
Requires Python: >=3.11
Keywords: json, jsonpatch, jsonpath, rename, rules-engine, toon, transform

# json-remap-engine

A Python package providing a JSONPath-driven remapping engine that produces JSON Patch operations.

This is the Python version of the [JavaScript json-remap-engine](https://github.com/rahulpowar/json-remap-engine) module, implementing the same interface and functionality.

## Features

- **100% JavaScript compatibility** - Same JSONPath syntax as the JavaScript version
- Transform JSON documents using JSONPath-based rules
- Generate JSON Patch operations (RFC 6902)
- Support for remove, replace, move, and **rename** operations
- **Comma-separated array indices** - `$.arr[1,3,5]` syntax fully supported
- **Rename rules** - Rename object keys in-place with literal or JSONPath targets
- **Multiple output formats** - JSON (pretty/compact) and TOON text format
- Comprehensive diagnostics and error reporting
- Type-safe rule creation helpers
- Full test suite (34/34 tests passing)

## Installation

```bash
uv add json-remap-engine
```

Or with pip:

```bash
pip install json-remap-engine

# Optional: for TOON text output support
pip install toon-llm
```

## Quick Start

```python
from json_remap_engine import (
    create_remove_rule,
    create_replace_rule,
    run_transformer,
    format_patch,
)

# Example document
document = {
    "user": {
        "name": "John Doe",
        "email": "john@example.com",
        "password": "secret123",
    },
    "items": ["a", "b", "c", "d", "e"]
}

# Define transformation rules
rules = [
    # Remove sensitive data
    create_remove_rule("$.user.password"),
    # Replace email with a sanitized version
    create_replace_rule("$.user.email", "****@example.com"),
    # Remove multiple array items using comma syntax (same as JavaScript!)
    create_remove_rule("$.items[1,3]"),  # Removes "b" and "d"
]

# Run the transformer
result = run_transformer(document, rules)

# Check the result
print(f"Success: {result['ok']}")
print(f"Transformed document: {result['document']}")
print(f"Operations: {format_patch(result['operations'])}")
```

### JSONPath Syntax

The Python version supports the **exact same JSONPath syntax** as the JavaScript version:

```python
# Comma-separated array indices (just like JavaScript!)
create_remove_rule("$.arr[1,3,5]")

# Array slices
create_remove_rule("$.arr[1:3]")

# Wildcards
create_replace_rule("$.items[*].active", True)

# Filter expressions
create_remove_rule("$.users[?(@.age < 18)]")

# Nested paths
create_replace_rule("$.user.profile.settings.theme", "dark")
```

## API

### Main Functions

- `run_transformer(document, rules)` - Apply transformation rules to a document
- `format_patch(operations, pretty=True)` - Format JSON Patch operations as JSON string

### Rule Creation

- `create_remove_rule(matcher, **options)` - Create a rule to remove matched values
- `create_replace_rule(matcher, value, **options)` - Create a rule to replace matched values
- `create_move_rule(matcher, target, **options)` - Create a rule to move matched values
- `create_rename_rule(matcher, target, **options)` - Create a rule to rename object properties

### Path Utilities

- `analysis_path_to_json_path(path)` - Convert analysis path to JSONPath
- `analysis_path_to_pointer(path)` - Convert analysis path to JSON Pointer
- `pointer_to_analysis_path(pointer)` - Convert JSON Pointer to analysis path
- `pointer_exists(document, pointer)` - Check if a pointer exists in document
- `get_value_at_pointer_safe(document, pointer)` - Safely get value at pointer
- `simple_json_path_to_pointer(expression)` - Convert simple JSONPath to pointer

## Rule Options

All rule creation functions support these options:

- `id` - Custom rule identifier (auto-generated if not provided)
- `allow_empty_matcher` - Allow matcher to resolve to zero paths without warning
- `allow_empty_value` - Allow value to be empty/undefined without raising warnings
- `disabled` - Start the rule disabled (returned in diagnostics but not executed)

Replace rules also support:
- `value_mode` - `"auto"` (default) or `"literal"` to control value interpretation

Move rules also support:
- `target_mode` - `"auto"` (default), `"pointer"`, or `"jsonpath"` to control target interpretation

Rename rules also support:
- `target_mode` - `"auto"` (default), `"literal"`, or `"jsonpath"` to control target interpretation

## Rename Rules

Rename rules allow you to change object property names in-place:

```python
from json_remap_engine import create_rename_rule, run_transformer

document = {
    "services": [
        {"service": {"id": "svc-1"}, "metadata": {"alias": "auth_service"}}
    ]
}

rules = [
    # Literal rename
    create_rename_rule("$.services[*].service", "svc"),

    # JSONPath-based rename (derives new name from document)
    create_rename_rule(
        "$.services[*].svc",
        "$.metadata.alias",
        target_mode="jsonpath"
    ),
]

result = run_transformer(document, rules)
# Result: {"services": [{"auth_service": {"id": "svc-1"}, "metadata": {...}}]}
```

Key features:
- Rename object properties without moving values
- Literal target or JSONPath expression
- Collision detection (prevents overwriting existing keys)
- Safety validation (blocks unsafe keys like `__proto__`)
- JSON Patch `move` operations for RFC compliance

## Output Formats

The transformer supports multiple output formats:

```python
from json_remap_engine import run_transformer, OutputEncoding

document = {"name": "Alice", "age": 30}
rules = []

# Default: no encoded output
result = run_transformer(document, rules)
# result["document"] contains the transformed data

# JSON pretty (human-readable)
result = run_transformer(document, rules, {"encoding": OutputEncoding.JSON_PRETTY})
print(result["output"])  # Pretty-printed JSON string

# JSON compact (minified)
result = run_transformer(document, rules, {"encoding": OutputEncoding.JSON_COMPACT})
print(result["output"])  # {"name":"Alice","age":30}

# TOON format (requires: pip install toon-llm)
result = run_transformer(document, rules, {"encoding": OutputEncoding.TOON})
print(result["output"])  # TOON-formatted text
```

## Development

This package uses [uv](https://docs.astral.sh/uv/) for dependency management.

```bash
# Install dependencies
uv sync --extra dev

# Run tests
uv run pytest tests/ -v

# Run example
uv run main.py

# Build package
uv build
```

## License

MIT - See [LICENSE](LICENSE) file for details.