Skip to main content

json-register

CI

Note: This library is currently in beta. The API is stable but may change in future releases based on user feedback and production usage.

json-register is a caching registry for JSON objects, with storage in a PostgreSQL database, using their JSONB encoding. It ensures that semantically equivalent JSON objects are cached only once by employing a canonicalisation strategy in the cache, and using JSONB comparisons in the database. The database assigns a uniqiue 32-bit integer identifier to each object.

This library is written in Rust and provides native bindings for Python, allowing for seamless integration into applications written in either language.

Features

  • Canonicalisation: JSON objects are canonicalised (keys sorted, whitespace removed) before storage to ensure uniqueness based on content.
  • Caching: An in-memory Least Recently Used (LRU) cache minimizes database lookups for frequently accessed objects.
  • PostgreSQL Integration: Efficiently stores and retrieves JSON data using PostgreSQL's JSONB type.
  • Batch Processing: Supports batch registration of objects to reduce network round-trips and improve throughput.
  • Cross-Language Support: Provides a native Rust API and a Python extension module.
  • Security: SQL injection prevention through identifier validation and automatic password sanitization in error messages.
  • Configurable Timeouts: Optional connection pool timeouts for acquire, idle, and maximum lifetime settings.
  • Monitoring: Query methods for connection pool metrics and cache hit rate statistics.

Installation

Rust

Add the following to your Cargo.toml:

[dependencies]
json-register = "0.3.0"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"

Python

Ensure you have a compatible Python environment (3.8+) and install the package.

Currently available on TestPyPI:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ json-register-rust

Once published to PyPI:

pip install json-register-rust

Database Schema

Before using json-register, create the required table and index in your PostgreSQL database:

CREATE TABLE IF NOT EXISTS json_objects (
    id SERIAL PRIMARY KEY,
    json_object JSONB UNIQUE NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_json_objects_gin ON json_objects USING GIN (json_object);

The GIN index enables efficient containment and path queries on the JSONB column. You can customise the table name, id column, and jsonb column names - just ensure they match your Register / JsonRegister configuration.

Usage

Rust Example

The following example demonstrates how to initialize the registry and register JSON objects using the Rust API.

use json_register::Register;
use serde_json::json;
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Configuration parameters
    let connection_string = "postgres://user:password@localhost:5432/dbname";
    let table_name = "json_objects";
    let id_column = "id";
    let jsonb_column = "data";
    let pool_size = 10;
    let lru_cache_size = 1000;

    // Initialize the register
    let register = Register::new(
        connection_string,
        table_name,
        id_column,
        jsonb_column,
        pool_size,
        lru_cache_size,
        None, // acquire_timeout_secs (defaults to 5)
        None, // idle_timeout_secs (defaults to 600)
        None, // max_lifetime_secs (defaults to 1800)
        None, // use_tls (defaults to false)
        None, // ca_cert_path (for private CAs)
    ).await?;

    // Register a single object
    let object = json!({
        "name": "Alice",
        "role": "Engineer",
        "active": true
    });

    let id = register.register_object(&object).await?;
    println!("Registered object with ID: {}", id);

    // Register a batch of objects
    let batch = vec![
        json!({"name": "Bob", "role": "Manager"}),
        json!({"name": "Charlie", "role": "Designer"}),
    ];

    let ids = register.register_batch_objects(&batch).await?;
    println!("Registered batch IDs: {:?}", ids);

    Ok(())
}

Python Example (Synchronous)

The following example demonstrates how to use the library within a Python application using the synchronous API.

from json_register import JsonRegister

def main():
    # Initialize the register
    register = JsonRegister(
        database_name="dbname",
        database_host="localhost",
        database_port=5432,
        database_user="user",
        database_password="password",
        lru_cache_size=1000,
        table_name="json_objects",
        id_column="id",
        jsonb_column="data",
        pool_size=10
    )

    # Register a single object
    obj = {
        "name": "Alice",
        "role": "Engineer",
        "active": True
    }

    obj_id = register.register_object(obj)
    print(f"Registered object with ID: {obj_id}")

    # Register a batch of objects
    batch = [
        {"name": "Bob", "role": "Manager"},
        {"name": "Charlie", "role": "Designer"}
    ]

    batch_ids = register.register_batch_objects(batch)
    print(f"Registered batch IDs: {batch_ids}")

if __name__ == "__main__":
    main()

Python Example (Asynchronous)

For async Python applications (FastAPI, aiohttp, etc.), use the async variants to avoid blocking the event loop.

from json_register import JsonRegister
import asyncio

async def main():
    # Initialize the register (constructor is synchronous)
    register = JsonRegister(
        database_name="dbname",
        database_host="localhost",
        database_port=5432,
        database_user="user",
        database_password="password",
        lru_cache_size=1000,
        table_name="json_objects",
        id_column="id",
        jsonb_column="data",
        pool_size=10
    )

    # Register a single object asynchronously
    obj = {
        "name": "Alice",
        "role": "Engineer",
        "active": True
    }

    obj_id = await register.register_object_async(obj)
    print(f"Registered object with ID: {obj_id}")

    # Register a batch of objects asynchronously
    batch = [
        {"name": "Bob", "role": "Manager"},
        {"name": "Charlie", "role": "Designer"}
    ]

    batch_ids = await register.register_batch_objects_async(batch)
    print(f"Registered batch IDs: {batch_ids}")

if __name__ == "__main__":
    asyncio.run(main())

Configuration

Timeout Parameters

Optional timeout parameters can be specified when initializing the register. All timeouts are in seconds.

  • acquire_timeout_secs: Timeout for acquiring a connection from the pool (default: 5)
  • idle_timeout_secs: Timeout before closing idle connections (default: 600)
  • max_lifetime_secs: Maximum lifetime of a connection (default: 1800)

Rust Example with Custom Timeouts

let register = Register::new(
    connection_string,
    table_name,
    id_column,
    jsonb_column,
    pool_size,
    lru_cache_size,
    Some(10),   // 10 second acquire timeout
    Some(300),  // 5 minute idle timeout
    Some(3600), // 1 hour max lifetime
    None,       // use_tls
    None,       // ca_cert_path
).await?;

Python Example with Custom Timeouts

register = JsonRegister(
    database_name="dbname",
    database_host="localhost",
    database_port=5432,
    database_user="user",
    database_password="password",
    acquire_timeout_secs=10,   # 10 second acquire timeout
    idle_timeout_secs=300,     # 5 minute idle timeout
    max_lifetime_secs=3600,    # 1 hour max lifetime
)

TLS Configuration

The library supports TLS for secure database connections, including custom CA certificates for private/internal environments.

Public CA (AWS RDS, Cloud SQL, etc.)

register = JsonRegister(
    database_name="dbname",
    database_host="db.example.com",
    database_port=5432,
    database_user="user",
    database_password="password",
    use_tls=True
)

Private CA (On-Premises / Internal)

For environments where PostgreSQL uses certificates signed by an internal CA:

register = JsonRegister(
    database_name="dbname",
    database_host="db.internal",
    database_port=5432,
    database_user="user",
    database_password="password",
    use_tls=True,
    ca_cert_path="/etc/ssl/certs/internal-ca.pem"
)
let register = Register::new(
    "postgres://user:password@db.internal:5432/dbname",
    "json_objects", "id", "json_object",
    10, 1000,
    None, None, None,
    Some(true),  // use_tls
    Some("/etc/ssl/certs/internal-ca.pem"),  // ca_cert_path
).await?;

When ca_cert_path is provided, TLS is automatically enabled (you don't need to also set use_tls=True, though it's recommended for clarity).

Security Logging

The library emits structured warnings at connection time for security-sensitive configurations:

  • WARN when TLS is disabled (plaintext connections)
  • WARN when no password is configured
  • WARN when custom CA certificates are loaded (with cert count and path)
  • ERROR if the CA certificate file cannot be read or parsed

These warnings are emitted via tracing (Rust) and bridged to Python's logging module automatically.

Monitoring

The library provides comprehensive telemetry metrics for integration with monitoring systems such as Prometheus, OpenTelemetry, or custom logging. All metrics can be retrieved individually or as a complete snapshot.

Connection Pool Metrics

  • pool_size(): Total number of connections in the pool (idle and active)
  • idle_connections(): Number of idle connections available for use
  • active_connections(): Number of connections currently in use
  • is_closed(): Whether the connection pool is closed

Cache Metrics

  • cache_hits(): Total number of successful cache lookups
  • cache_misses(): Total number of unsuccessful cache lookups
  • cache_hit_rate(): Hit rate as a percentage (0.0 to 100.0)
  • cache_size(): Current number of items in the cache
  • cache_capacity(): Maximum cache capacity
  • cache_evictions(): Total number of items evicted from the cache

Database Metrics

  • db_queries_total(): Total number of database queries executed
  • db_query_errors(): Total number of failed database queries

Operation Metrics

  • register_single_calls(): Number of times register_object was called
  • register_batch_calls(): Number of times register_batch_objects was called
  • total_objects_registered(): Total number of objects registered across all calls

Telemetry Snapshot

The telemetry_metrics() method (Rust only) returns a complete snapshot of all metrics in a single call, which is useful for OpenTelemetry exporters

Rust Monitoring Example

// Get all metrics at once (recommended for OpenTelemetry)
let metrics = register.telemetry_metrics();
println!("Cache: {}/{} items, {} evictions", metrics.cache_size, metrics.cache_capacity, metrics.cache_evictions);
println!("Cache performance: {} hits, {} misses ({:.2}% hit rate)",
    metrics.cache_hits, metrics.cache_misses, metrics.cache_hit_rate);
println!("Pool: {} total, {} active, {} idle",
    metrics.pool_size, metrics.active_connections, metrics.idle_connections);
println!("Database: {} queries, {} errors",
    metrics.db_queries_total, metrics.db_query_errors);
println!("Operations: {} objects registered ({} single + {} batch calls)",
    metrics.total_objects_registered, metrics.register_single_calls, metrics.register_batch_calls);

// Or query individual metrics
let hit_rate = register.cache_hit_rate();
let active = register.active_connections();

Python Monitoring Example

# Individual metrics
print(f"Cache: {register.cache_size()}/{register.cache_capacity()} items")
print(f"Cache evictions: {register.cache_evictions()}")
print(f"Active connections: {register.active_connections()}")
print(f"DB queries: {register.db_queries_total()}, errors: {register.db_query_errors()}")
print(f"Objects registered: {register.total_objects_registered()}")
print(f"Single calls: {register.register_single_calls()}, Batch calls: {register.register_batch_calls()}")

Logging

The library uses the tracing crate for structured logging. Logs include connection info, cache hit/miss statistics, and batch sizes.

Rust

Use tracing-subscriber to see logs:

use tracing_subscriber::EnvFilter;

tracing_subscriber::fmt()
    .with_env_filter(EnvFilter::from_default_env())
    .init();

Set the RUST_LOG environment variable to control log levels:

# See debug logs from json-register
RUST_LOG=json_register=debug cargo run

# See trace logs (cache hits/misses)
RUST_LOG=json_register=trace cargo run

Python

Logs are automatically bridged to Python's logging module:

import logging

# Configure Python logging as usual
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)s %(name)s: %(message)s'
)

# Logs from json-register will appear with logger name 'json_register'
# You can also configure just the json_register logger:
logging.getLogger('json_register').setLevel(logging.DEBUG)

Log Levels

Level Content
INFO Connection events, configuration
DEBUG Cache statistics, batch sizes, database queries
TRACE Individual cache hits/misses (verbose)

License

This project is licensed under the Apache-2.0 License.

Release files for telicent-json-register 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for telicent-json-register 0.3.1
File Size Uploaded
telicent_json_register-0.3.1.tar.gz 44.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for telicent-json-register 0.3.1
File
telicent_json_register-0.3.1-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details
telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_x86_64.whl CPython 3.8 abi3 Linux glibc 2.34+ x86-64 Details
telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_aarch64.whl CPython 3.8 abi3 Linux glibc 2.34+ ARM64 Details
telicent_json_register-0.3.1-cp38-abi3-macosx_11_0_arm64.whl CPython 3.8 abi3 macOS 11.0+ ARM64 Details
telicent_json_register-0.3.1-cp38-abi3-macosx_10_12_x86_64.whl CPython 3.8 abi3 macOS 10.12+ x86-64 Details

Total release size:14.1 MB

Release files / telicent_json_register-0.3.1.tar.gz

Download URL telicent_json_register-0.3.1.tar.gz
Size 44.3 kB
Tags Source
SHA-256 checksum
How to use checksums
4f0dbdba87a85b0fcf5f03440669247dcd05c1423b7c4e6249e95e1ad2806c56
BLAKE2b-256 checksum
How to use checksums
8544a5971006c47f75f5317dee3bd73ce49b3683f2dac4e27f82c144b0638c98
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / telicent_json_register-0.3.1-cp38-abi3-win_amd64.whl

Download URL telicent_json_register-0.3.1-cp38-abi3-win_amd64.whl
Size 2.4 MB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
9202601c0bd86240cb3f4df443b32367b40a875a12cedbaa1d9cff099f4dfa57
BLAKE2b-256 checksum
How to use checksums
caa2cd0f402db007477d738bd49d704844a9c06cf575bed816f444bc6225b700
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_x86_64.whl

Download URL telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_x86_64.whl
Size 3.1 MB
Tags CPython 3.8 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
8a75ff7fbc7d1cbac4db167d3dab90e031355b7f531a7126f8b7570733af113a
BLAKE2b-256 checksum
How to use checksums
fd979730f12e9476b7399a57e8656d23d3fc7e9fe682544f9e507b2d4e9f996a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_aarch64.whl

Download URL telicent_json_register-0.3.1-cp38-abi3-manylinux_2_34_aarch64.whl
Size 3.0 MB
Tags CPython 3.8 Linux glibc 2.34+ ARM64 abi3
SHA-256 checksum
How to use checksums
2bee08be57bc9916a879ee5c8a285bf4fa3bac3e4de2b969bc21170fefc8b02c
BLAKE2b-256 checksum
How to use checksums
b52def5ecc32f133936bc293c153d58ce29d1f17d79d0bc97a179465c7848e7a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / telicent_json_register-0.3.1-cp38-abi3-macosx_11_0_arm64.whl

Download URL telicent_json_register-0.3.1-cp38-abi3-macosx_11_0_arm64.whl
Size 2.8 MB
Tags CPython 3.8 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9f20ce21429f70cbce923a4e7e61c39826c302e6d4dccf6771595a273d28fb8c
BLAKE2b-256 checksum
How to use checksums
3d22bfe9da34fd11597ba4e168d5d420b238e4060aa6d770d44560866c55918d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / telicent_json_register-0.3.1-cp38-abi3-macosx_10_12_x86_64.whl

Download URL telicent_json_register-0.3.1-cp38-abi3-macosx_10_12_x86_64.whl
Size 2.9 MB
Tags CPython 3.8 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
f0a7407efbf343ee2dbd573898fc7042898c333790d3d3998a45cab4175172dd
BLAKE2b-256 checksum
How to use checksums
aed3fa308b2948f07e6cffbad26ba8dbadc0251aef339a4f574128caf01c00e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.1 This release

6 release files

0.3.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page