check-serialization

Analyzes PHP code for serialization overhead. Detects inefficient JSON encoding, large object hydration, missing JsonSerializable, circular reference issues.

59 stars

Best use case

check-serialization is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Analyzes PHP code for serialization overhead. Detects inefficient JSON encoding, large object hydration, missing JsonSerializable, circular reference issues.

Teams using check-serialization should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/check-serialization/SKILL.md --create-dirs "https://raw.githubusercontent.com/dykyi-roman/awesome-claude-code/main/skills/check-serialization/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/check-serialization/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How check-serialization Compares

Feature / Agentcheck-serializationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Analyzes PHP code for serialization overhead. Detects inefficient JSON encoding, large object hydration, missing JsonSerializable, circular reference issues.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Serialization Performance Analysis

Analyze PHP code for serialization/deserialization performance issues.

## Detection Patterns

### 1. Large Object Serialization

```php
// PROBLEMATIC: Serializing entire entity with relations
$users = $this->userRepository->findAll();
return json_encode($users); // Includes all properties, relations, metadata

// PROBLEMATIC: Full Doctrine entity serialization
$response = new JsonResponse($this->em->find(User::class, $id));
// Serializes proxy objects, lazy-loaded relations, internal state

// PROBLEMATIC: Large collection in single response
$orders = $this->orderRepository->findByUser($userId);
return json_encode($orders); // Thousands of objects
```

### 2. N+1 During Serialization

```php
// PROBLEMATIC: Lazy loading triggered during serialization
class UserResource
{
    public function toArray(User $user): array
    {
        return [
            'id' => $user->getId(),
            'name' => $user->getName(),
            'orders' => $user->getOrders()->toArray(), // Lazy load!
            'profile' => $user->getProfile()->toArray(), // Another query!
        ];
    }
}

// PROBLEMATIC: Multiple users with relations
$users = $repository->findAll();
foreach ($users as $user) {
    $data[] = [
        'user' => $user->getName(),
        'department' => $user->getDepartment()->getName(), // N+1
    ];
}
```

### 3. Missing JsonSerializable

```php
// PROBLEMATIC: Public properties exposed
class User
{
    public int $id;
    public string $email;
    public string $passwordHash; // Exposed!
    public ?string $apiToken; // Exposed!
}

// Becomes {"id":1,"email":"...","passwordHash":"...","apiToken":"..."}

// FIXED: Implement JsonSerializable
class User implements JsonSerializable
{
    public function jsonSerialize(): array
    {
        return [
            'id' => $this->id,
            'email' => $this->email,
            // Sensitive fields excluded
        ];
    }
}
```

### 4. Circular Reference Issues

```php
// PROBLEMATIC: Circular reference causes error/infinite loop
class Order
{
    public User $user;
}

class User
{
    public array $orders; // Contains Order objects
}

json_encode($user); // Error: circular reference

// PROBLEMATIC: Doctrine bidirectional relations
/**
 * @ORM\OneToMany(targetEntity=Order::class, mappedBy="user")
 */
private Collection $orders;

/**
 * @ORM\ManyToOne(targetEntity=User::class, inversedBy="orders")
 */
private User $user;
```

### 5. DateTime Serialization Overhead

```php
// PROBLEMATIC: DateTime as object
$data = [
    'created' => $entity->getCreatedAt(), // DateTime object
];
json_encode($data);
// {"created":{"date":"2024-01-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"}}

// PROBLEMATIC: Multiple DateTime conversions
foreach ($events as $event) {
    $data[] = [
        'start' => $event->getStart()->format('Y-m-d H:i:s'),
        'end' => $event->getEnd()->format('Y-m-d H:i:s'),
        'created' => $event->getCreated()->format('Y-m-d H:i:s'),
    ];
}
```

### 6. Binary Data in JSON

```php
// PROBLEMATIC: Binary data base64 encoded in JSON
$response = [
    'image' => base64_encode($imageData), // 33% size increase
    'file' => base64_encode($fileContent),
];
json_encode($response);

// PROBLEMATIC: Large file content in response
$data = [
    'attachment' => base64_encode(file_get_contents($path)),
];
// Should be streamed or served separately
```

### 7. Deep Nested Structures

```php
// PROBLEMATIC: Deeply nested JSON
$data = [
    'user' => [
        'profile' => [
            'settings' => [
                'preferences' => [
                    'notifications' => [...],
                ],
            ],
        ],
    ],
];
// Deep recursion during serialize/deserialize

// PROBLEMATIC: Recursive tree serialization
public function toArray(): array
{
    return [
        'id' => $this->id,
        'children' => array_map(
            fn($child) => $child->toArray(), // Unlimited depth
            $this->children
        ),
    ];
}
```

### 8. Hydration Overhead

```php
// PROBLEMATIC: Full object hydration for read-only display
$users = $this->em->createQueryBuilder()
    ->select('u')
    ->from(User::class, 'u')
    ->getQuery()
    ->getResult(); // Full entity hydration

// Full objects just to extract a few fields
foreach ($users as $user) {
    $data[] = ['id' => $user->getId(), 'name' => $user->getName()];
}

// BETTER: Scalar hydration
$users = $this->em->createQueryBuilder()
    ->select('u.id', 'u.name')
    ->from(User::class, 'u')
    ->getQuery()
    ->getScalarResult(); // Just arrays
```

### 9. Inefficient Collection Serialization

```php
// PROBLEMATIC: Converting entire collection multiple times
$users = $repository->findAll();
$mapped = array_map(fn($u) => $u->toArray(), $users->toArray());
$json = json_encode($mapped);

// PROBLEMATIC: Multiple iterations
$data = $collection->toArray();
$filtered = array_filter($data, fn($item) => $item->isActive());
$mapped = array_map(fn($item) => $item->toArray(), $filtered);
// 3 full iterations

// BETTER: Single pass with generators
function toJson(iterable $items): string
{
    $data = [];
    foreach ($items as $item) {
        if ($item->isActive()) {
            $data[] = $item->toArray();
        }
    }
    return json_encode($data);
}
```

### 10. Missing Response Caching

```php
// PROBLEMATIC: Serializing same data repeatedly
public function getConfig(): JsonResponse
{
    $config = $this->configService->getAll();
    return new JsonResponse($config); // Serialized every request
}

// PROBLEMATIC: User data serialized each time
public function getCurrentUser(): JsonResponse
{
    $user = $this->userService->getCurrent();
    return new JsonResponse($user->toArray()); // No caching
}
```

## Grep Patterns

```bash
# json_encode on entities
Grep: "json_encode\s*\(\s*\\\$this->(em|repository|entityManager)" --glob "**/*.php"

# Large array serialization
Grep: "json_encode\s*\([^)]*findAll|json_encode\s*\([^)]*getResult" --glob "**/*.php"

# Missing JsonSerializable
Grep: "class.*\{" --glob "**/*.php" # Then check for JsonSerializable

# base64_encode in JSON context
Grep: "base64_encode.*json_encode|json_encode.*base64_encode" --glob "**/*.php"

# DateTime in response
Grep: "->format\s*\(" --glob "**/*.php"
```

## References

- `references/examples.md` — Secure patterns: DTOs, eager loading, circular ref handling, streaming, caching, pagination

## Severity Classification

| Pattern | Severity |
|---------|----------|
| N+1 during serialization | 🔴 Critical |
| Full entity in JSON response | 🔴 Critical |
| Circular reference without handling | 🔴 Critical |
| Large binary data in JSON | 🟠 Major |
| Missing JsonSerializable (sensitive data) | 🟠 Major |
| Deep nested structures | 🟠 Major |
| Full hydration for read-only | 🟡 Minor |
| DateTime objects in response | 🟡 Minor |

## Output Format

```markdown
### Serialization Issue: [Description]

**Severity:** 🔴/🟠/🟡
**Location:** `file.php:line`
**Impact:** [Response size, CPU overhead, memory usage]

**Issue:**
[Description of the serialization problem]

**Code:**
```php
// Problematic code
```

**Fix:**
```php
// Optimized serialization
```

**Expected Improvement:**
- Response size: 50KB → 2KB (DTO instead of entity)
- Query count: N+1 → 1 (eager loading)
- CPU time: -60% (cached serialization)
```

Related Skills

create-health-check

59
from dykyi-roman/awesome-claude-code

Generates Health Check pattern for PHP 8.4. Creates application-level health endpoints with component checkers (Database, Redis, RabbitMQ), status aggregation, and RFC-compliant JSON response. Includes unit tests.

create-docker-healthcheck

59
from dykyi-roman/awesome-claude-code

Generates Docker health check scripts for PHP services. Creates PHP-FPM, Nginx, and custom endpoint health checks.

check-xxe

59
from dykyi-roman/awesome-claude-code

Analyzes PHP code for XML External Entity vulnerabilities. Detects unsafe XML parsers, missing entity protection, LIBXML flags issues, XSLT attacks.

check-version-consistency

59
from dykyi-roman/awesome-claude-code

Audits version consistency across project files. Checks composer.json, README, CHANGELOG, docs, and configuration files for version number synchronization.

check-type-juggling

59
from dykyi-roman/awesome-claude-code

Detects PHP type juggling vulnerabilities. Identifies loose comparison with user input, in_array without strict mode, switch statement type coercion, and hash comparison bypasses.

check-timeout-strategy

59
from dykyi-roman/awesome-claude-code

Audits timeout configuration across HTTP clients, database connections, queue consumers, cache operations, and external service calls. Detects missing or misconfigured timeouts.

check-test-quality

59
from dykyi-roman/awesome-claude-code

Analyzes PHP test code quality. Checks test structure, assertion quality, test isolation, naming conventions, AAA pattern adherence.

check-ssrf

59
from dykyi-roman/awesome-claude-code

Analyzes PHP code for SSRF vulnerabilities. Detects unvalidated URLs, internal network access, DNS rebinding, cloud metadata access, URL parsing bypass attempts.

check-sql-injection

59
from dykyi-roman/awesome-claude-code

Analyzes PHP code for SQL injection vulnerabilities. Detects query concatenation, ORM misuse, raw queries, dynamic identifiers, prepared statement bypasses.

check-sensitive-data

59
from dykyi-roman/awesome-claude-code

Analyzes PHP code for sensitive data exposure. Detects plaintext secrets, exposed credentials, PII in logs, insecure storage, hardcoded keys.

check-secure-headers

59
from dykyi-roman/awesome-claude-code

Audits HTTP security headers configuration. Checks CSP, X-Frame-Options, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and cache control headers.

check-scalability-readiness

59
from dykyi-roman/awesome-claude-code

Analyzes PHP code for scalability issues. Detects file-based sessions, in-memory state, hardcoded hostnames, filesystem-dependent state, and missing stateless design patterns.