Skip to content

Implement comprehensive compound document validation for JSON:API#24

Merged
intel352 merged 2 commits intomainfrom
copilot/fix-9
Sep 17, 2025
Merged

Implement comprehensive compound document validation for JSON:API#24
intel352 merged 2 commits intomainfrom
copilot/fix-9

Conversation

Copy link
Contributor

Copilot AI commented Sep 16, 2025

This PR implements complete compound document validation for JSON:API v1.1 specification compliance, addressing all the validation gaps identified in the issue.

Changes Made

The implementation adds comprehensive validation for compound documents through new validation functions in DocumentValidator.js:

1. Included/Data Member Pairing

Validates that included member is only present when data member exists:

// ❌ Invalid - included without data
{
  "included": [...],
  "meta": {...}
}

// ✅ Valid - included with data
{
  "data": {...},
  "included": [...]
}

2. Resource Linkage Validation

Ensures all included resources are actually referenced from primary data relationships:

// ❌ Invalid - orphaned resource
{
  "data": {
    "relationships": {
      "author": { "data": { "type": "people", "id": "1" }}
    }
  },
  "included": [
    { "id": "1", "type": "people" },
    { "id": "2", "type": "people" }  // Orphaned - not referenced
  ]
}

3. Duplicate Resource Detection

Identifies duplicate resources in the included array by type:id:

// ❌ Invalid - duplicate resource
{
  "included": [
    { "id": "1", "type": "people", "attributes": {"name": "John"} },
    { "id": "1", "type": "people", "attributes": {"name": "Jane"} }  // Duplicate
  ]
}

4. Edge Case Handling

Properly handles scenarios like data: null with included resources:

// ❌ Invalid - all included resources become orphaned when data is null
{
  "data": null,
  "included": [...]
}

Key Features

  • Precise Error Messages: Clear, actionable error messages with context about which resources are problematic
  • Comprehensive Linkage Analysis: Tracks which resources are referenced vs included, identifying both orphaned resources (errors) and missing resources (warnings)
  • JSON:API Spec Compliant: Recognizes that bidirectional relationships are normal and expected in JSON:API
  • Minimal Performance Impact: Efficient Set-based algorithms for duplicate detection and linkage analysis
  • Backward Compatible: All existing validation continues to work unchanged

Testing

All validation scenarios have been thoroughly tested:

  • Valid compound documents pass validation
  • Invalid scenarios are correctly detected and reported with specific error messages
  • Real API responses from the mock server validate successfully
  • Edge cases (null data, empty arrays, complex relationships) are handled properly
  • Code passes all linting requirements with zero warnings

The implementation provides clear reporting for compound document issues while maintaining compatibility with existing JSON:API validation functionality.

Fixes #9.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copilot AI changed the title [WIP] Validate Included Resources and Compound Documents Implement comprehensive compound document validation for JSON:API Sep 17, 2025
Copilot AI requested a review from intel352 September 17, 2025 00:12
@intel352
Copy link
Contributor

@copilot Take a screenshot showing the change in relation to the validator UI

Copy link
Contributor Author

Copilot AI commented Sep 17, 2025

@copilot Take a screenshot showing the change in relation to the validator UI

Here's a screenshot showing the new compound document validation features in action. The validator now includes four new validation tests (highlighted in green):

  1. Compound Document Structure - Ensures included member is only present when data exists
  2. Included Resource Duplicates - Detects duplicate resources in the included array
  3. Resource Linkage - Verifies all included resources are referenced from primary data relationships
  4. Circular References - Analyzes relationship structure (informational, as bidirectional relationships are normal in JSON:API)

The screenshot shows a successful validation of a compound document with 89 tests passed, including the new compound document validations testing an endpoint with ?include=author,comments that returns an article with its related author and comments.

Compound Document Validation UI

@intel352 intel352 marked this pull request as ready for review September 17, 2025 00:55
Copilot AI review requested due to automatic review settings September 17, 2025 00:55
@intel352 intel352 merged commit b38e492 into main Sep 17, 2025
1 check passed
@intel352 intel352 deleted the copilot/fix-9 branch September 17, 2025 00:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements comprehensive compound document validation for JSON:API v1.1 specification, adding critical validation rules for included resources and their relationships with primary data.

  • Validates that included member only appears when data member exists
  • Implements resource linkage validation to detect orphaned included resources
  • Adds duplicate resource detection in included arrays


return {
total: totalRelationships,
bidirectional: Math.floor(bidirectionalCount / 2) // Each bidirectional pair is counted twice
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bidirectional count calculation is incorrect. The current logic counts each relationship individually but then divides by 2, which doesn't properly identify bidirectional pairs. A bidirectional relationship should only be counted once when both A->B and B->A exist.

Copilot uses AI. Check for mistakes.
Comment on lines +841 to +844
// Check if reverse relationship exists
if (relationships.has(reverseRelationshipPair)) {
bidirectionalCount++
}
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic will count each bidirectional relationship twice (once for each direction), but the division by 2 at line 854 assumes this double-counting. However, the increment happens for every relationship that has a reverse, not just when discovering a bidirectional pair for the first time.

Copilot uses AI. Check for mistakes.
const orphanedResources = []
includedResources.forEach(resourceKey => {
if (!referencedResources.has(resourceKey)) {
const [type, id] = resourceKey.split(':')
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The split(':') operation is unsafe if resource IDs contain colons. Since JSON:API allows any string as an ID, this could incorrectly parse resource keys like 'user:admin:123' where the ID is 'admin:123'.

Copilot uses AI. Check for mistakes.
const missingResources = []
referencedResources.forEach(resourceKey => {
if (!includedResources.has(resourceKey)) {
const [type, id] = resourceKey.split(':')
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The split(':') operation is unsafe if resource IDs contain colons. Since JSON:API allows any string as an ID, this could incorrectly parse resource keys like 'user:admin:123' where the ID is 'admin:123'.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate Included Resources and Compound Documents

3 participants