xpat23/xpat-json-object

Immutable object-oriented JSON manipulation library with clean dot notation API for PHP

v1.0.0 2025-07-12 01:14 UTC

This package is auto-updated.

Last update: 2025-07-12 01:22:35 UTC


README

Latest Version PHP Version License

A clean, immutable, object-oriented JSON manipulation library for PHP with intuitive dot notation API.

Why xpat-json-object?

  • 🔒 Immutable - All operations return new instances, original data never changes
  • 🎯 Dot notation - Access nested data with simple get('user.settings.theme') syntax
  • ⚡ Fluent API - Chain operations naturally with $json->set('key', 'value')->remove('old')
  • 🏗️ Object-oriented - Clean OOP design, no global functions or static abuse
  • 🛡️ Type safe - Built for PHP 8.1+ with proper type declarations
  • 📦 Zero dependencies - Pure PHP, no external requirements

Installation

composer require xpat23/xpat-json-object

Quick Start

use Xpat\JsonObject\JsonObject;

// Create from array
$json = JsonObject::fromArray([
    'user' => [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'settings' => [
            'theme' => 'dark',
            'notifications' => true
        ]
    ]
]);

// Access nested data with dot notation
echo $json->get('user.name'); // "John Doe"
echo $json->get('user.settings.theme'); // "dark"

// Check if keys exist
if ($json->has('user.settings.notifications')) {
    echo 'User has notification settings';
}

// Immutable operations - returns new instances
$updated = $json
    ->set('user.age', 30)
    ->set('user.settings.language', 'en')
    ->remove('user.settings.notifications');

// Original unchanged, $updated is a new instance
echo $json->get('user.age'); // null (original unchanged)
echo $updated->get('user.age'); // 30 (new instance)

Features

Factory Methods

// From array
$json = JsonObject::fromArray(['key' => 'value']);

// From JSON string
$json = JsonObject::fromString('{"key": "value"}');

// From file
$json = JsonObject::fromFile('config.json');

// Empty object
$json = JsonObject::empty();

Dot Notation Access

$json = JsonObject::fromArray([
    'app' => [
        'database' => [
            'host' => 'localhost',
            'port' => 3306
        ]
    ]
]);

// Get values
$host = $json->get('app.database.host'); // "localhost"
$port = $json->get('app.database.port', 5432); // 3306, with default fallback

// Check existence
$hasHost = $json->has('app.database.host'); // true
$hasPassword = $json->has('app.database.password'); // false

Immutable Operations

// All operations return new instances
$original = JsonObject::fromArray(['count' => 1]);

$incremented = $original->set('count', 2);
$withExtra = $incremented->set('extra', 'data');
$removed = $withExtra->remove('extra');

// Chain operations fluently
$result = JsonObject::empty()
    ->set('user.name', 'Jane')
    ->set('user.email', 'jane@example.com')
    ->set('user.active', true);

Data Transformation

$numbers = JsonObject::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);

// Filter
$evens = $numbers->filter(fn($value) => $value % 2 === 0);

// Map
$doubled = $numbers->map(fn($value) => $value * 2);

// Transform
$squared = $numbers->transform(fn($data) => 
    array_map(fn($v) => $v * $v, $data)
);

Merging

$config1 = JsonObject::fromArray([
    'database' => ['host' => 'localhost']
]);

$config2 = JsonObject::fromArray([
    'database' => ['port' => 3306, 'name' => 'myapp']
]);

// Deep merge
$merged = $config1->deepMerge($config2);
// Result: ['database' => ['host' => 'localhost', 'port' => 3306, 'name' => 'myapp']]

Subsetting

$user = JsonObject::fromArray([
    'id' => 1,
    'name' => 'John',
    'email' => 'john@example.com',
    'password' => 'secret',
    'settings' => ['theme' => 'dark']
]);

// Get only specific keys
$public = $user->only(['id', 'name', 'email']);

// Get all except specific keys
$safe = $user->except(['password']);

Export Methods

// To array
$array = $json->toArray();

// To JSON string
$jsonString = $json->toJson();

// Pretty JSON
$prettyJson = $json->toPrettyJson();

// Get all available keys
$keys = $json->keys(); // ['user.name', 'user.email', 'user.settings.theme']

Utility Methods

// Count root level items
$count = $json->count();

// Check if empty
$isEmpty = $json->isEmpty();

// Get all dot notation keys
$allKeys = $json->keys();

Advanced Usage

Working with APIs

// Parse API response
$response = JsonObject::fromString($apiResponse);

// Extract specific data
$userData = $response->only([
    'user.id',
    'user.name',
    'user.profile.avatar'
]);

// Transform for frontend
$frontendData = $userData
    ->set('user.displayName', $userData->get('user.name'))
    ->set('user.hasAvatar', $userData->has('user.profile.avatar'))
    ->remove('user.name');

Configuration Management

// Load config files
$appConfig = JsonObject::fromFile('config/app.json');
$dbConfig = JsonObject::fromFile('config/database.json');

// Merge configurations
$config = $appConfig->deepMerge($dbConfig);

// Environment-specific overrides
if ($environment === 'production') {
    $config = $config->set('app.debug', false);
}

Data Validation Pipeline

$data = JsonObject::fromArray($inputData);

// Validate and transform
$validated = $data
    ->filter(fn($value, $key) => !empty($value)) // Remove empty values
    ->set('created_at', date('Y-m-d H:i:s'))     // Add timestamp
    ->remove('_token');                          // Remove CSRF token

if (!$validated->has('email')) {
    throw new InvalidArgumentException('Email is required');
}

Requirements

  • PHP 8.1 or higher
  • JSON extension (typically included with PHP)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Testing

# Run tests
composer test

# Run tests with coverage
composer test-coverage

# Run static analysis
composer phpstan

# Check code style
composer cs-check

# Fix code style
composer cs-fix

# Run all quality checks
composer quality

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

v1.0.0

  • Initial release
  • Immutable JsonObject with dot notation support
  • Factory methods for creating instances
  • Fluent API for chaining operations
  • Data transformation methods
  • Merge and subset operations

Support

Made with ❤️ by xpat