Use when the user needs help with path queries, JSON transformations, schema validation, or safe JSON editing workflows. Triggered by questions about JSON operations, data extraction, file merging, or validation strategies.
Install
npx skillscat add mearman/marketplace/json-manipulation-patterns Install via the SkillsCat registry.
Provides comprehensive guidance on JSON file manipulation patterns, simple path query syntax, transformation strategies, validation approaches, and safe editing workflows.
Simple Path Query Syntax
Basic Path Expressions
Property access:
name- Direct propertyuser.name- Nested property (dot notation)config.server.host- Deep nesting
Array access:
items[0]- First elementitems[1]- Second elementusers[5].name- Property of array element
Wildcards:
users[*]- All array elementsusers[*].email- Property from all array elements*.id- All id properties at current leveldata.*.value- All value properties in data object
Complex Paths
Mixed notation:
users[0].orders[*].items[0].pricePrice of first item in all orders of first user.
Wildcard mapping:
products[*].tags[*]All tags from all products (flattened).
Nested wildcards:
categories[*].items[*].nameNames of all items in all categories.
What's NOT Supported
For complex filtering logic, use TypeScript transform scripts instead:
Filtering by condition (NOT supported in paths):
// Use transform script instead of path queries
export default (data: any) => {
return data.users.filter(u => u.age > 18);
};Recursive descent (NOT supported):
// NOT: $..email (find all emails anywhere)
// Instead: Use specific paths or transform scriptsArray slicing (NOT supported):
// NOT: items[0:5] (first 5 items)
// Instead: Use transform script with slice()Transformation Patterns
Data Filtering
Remove inactive items:
export default (data: any) => {
data.items = data.items.filter((item: any) => item.active);
return data;
};Filter by date:
export default (data: any) => {
const cutoff = new Date('2024-01-01');
data.records = data.records.filter((r: any) =>
new Date(r.date) >= cutoff
);
return data;
};Data Mapping
Transform structure:
export default (data: any) => ({
version: "2.0",
items: data.items.map((item: any) => ({
id: item.itemId,
name: item.itemName,
price: item.cost * 1.1, // Add 10% markup
}))
});Normalize data:
export default (data: any) => {
data.users = data.users.map((user: any) => ({
...user,
email: user.email.toLowerCase(),
name: user.name.trim(),
}));
return data;
};Data Aggregation
Add computed fields:
export default (data: any) => {
data.summary = {
totalItems: data.items.length,
totalValue: data.items.reduce((sum: number, item: any) =>
sum + item.price, 0
),
averagePrice: data.items.reduce((sum: number, item: any) =>
sum + item.price, 0) / data.items.length,
};
return data;
};Group by category:
export default (data: any) => {
const grouped = data.items.reduce((acc: any, item: any) => {
const category = item.category || 'uncategorized';
if (!acc[category]) acc[category] = [];
acc[category].push(item);
return acc;
}, {});
return { categories: grouped };
};Data Migration
Version upgrade:
export default (data: any) => {
// Migrate from v1 to v2 format
if (data.version === "1.0") {
return {
version: "2.0",
config: {
...data.settings,
newField: "default",
},
data: data.items,
};
}
return data;
};Rename properties:
export default (data: any) => {
return {
...data,
items: data.items.map((item: any) => ({
id: item.itemId, // Rename itemId -> id
title: item.name, // Rename name -> title
cost: item.price, // Rename price -> cost
}))
};
};Schema Validation Strategies
Design JSON Schemas
Basic structure:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "number", "minimum": 0 }
},
"required": ["name"]
}Array validation:
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"value": { "type": "number" }
},
"required": ["id", "value"]
},
"minItems": 1
}
}
}Enum and patterns:
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["active", "inactive", "pending"]
},
"email": {
"type": "string",
"format": "email"
},
"phone": {
"type": "string",
"pattern": "^\\d{3}-\\d{3}-\\d{4}$"
}
}
}Validation Workflow
- Define schema for your data structure
- Validate before edits to catch issues early
- Validate after edits to ensure correctness
- Store schemas in version control alongside data
Common Validation Scenarios
Configuration validation:
- Ensure required fields present
- Validate value ranges
- Check format of URLs, emails, etc.
API response validation:
- Verify response structure
- Check data types
- Ensure required fields exist
Data migration validation:
- Validate source data before transform
- Validate transformed data against new schema
- Ensure no data loss
Safe Editing Workflows
Pre-Edit Checklist
Backup verification:
- Auto-backup is enabled by default
- Backups stored as
.bakfiles - Check backup location before destructive operations
Dry-run testing:
- Always use
--dry-run truefor new operations - Review changes before applying
- Verify path matches expected locations
- Always use
Validation:
- Validate JSON before editing
- Validate after editing to ensure correctness
- Use schemas to enforce constraints
Destructive Operations
Delete operations:
1. Query first: See what will be deleted
2. Dry-run: Preview deletion
3. Confirm: Verify backup created
4. Execute: Apply deletionBatch operations:
1. Test on single file first
2. Dry-run on all files
3. Review each file's changes
4. Apply to all files
5. Validate all resultsRecovery from Mistakes
Restore from backup:
# Backups are `.bak` files in same directory
cp data.json.bak data.jsonRevert specific change:
- Query backup file for original value
- Set original value in current file
- Validate result
Best Practices
For simple edits:
- Use
setoperation with explicit paths - Avoid wildcards unless necessary
- Validate path with query first
For complex transformations:
- Write TypeScript transform script
- Test on copy of data first
- Use dry-run to preview result
- Keep transform scripts in version control
For batch operations:
- Test on single file first
- Use explicit file lists (avoid
*until tested) - Check each result
- Keep backups until verified
Merge Strategies
Deep Merge
- Use when: Merging configuration files with nested objects
- Behavior: Recursively merges objects, concatenates arrays
- Example: Base config + environment-specific overrides
Shallow Merge
- Use when: Top-level property replacement needed
- Behavior: Only merges first level, later values win
- Example: Simple key-value configurations
Concat
- Use when: Combining array-based files
- Behavior: Flattens all arrays into single array
- Example: Merging multiple data files
Merge Order Matters
Files are merged left-to-right:
file1.json + file2.json + file3.jsonfile3values overridefile2file2values overridefile1
Place most general config first, most specific last.
Performance Considerations
Large Files
Query optimization:
- Use specific paths:
users[0].nameinstead of*[*].name - Access nested data directly:
config.server.hostinstead of wildcards - For complex filtering, use transform scripts instead of repeated queries
Transform optimization:
- Process in chunks for very large files
- Use streaming for files over 100MB
- Consider splitting into multiple files
Batch operations:
- Process files in parallel when possible
- Use specific file lists, not wildcards
- Monitor memory usage for many files
Common Patterns
Configuration Management
Base + Override pattern:
1. Base config (defaults)
2. Environment config (dev/staging/prod)
3. Local overrides (optional)
Merge order: base → env → localValidation workflow:
1. Validate base config
2. Merge with overrides
3. Validate merged result
4. DeployData Pipeline
Extract-Transform-Load:
1. Query: Extract relevant data
2. Transform: Apply TypeScript transformation
3. Validate: Check against schema
4. Load: Write to destinationVersion Migration
Safe migration:
1. Query current version
2. Backup original
3. Transform to new version
4. Validate against new schema
5. Test with application
6. DeployTroubleshooting
Query Returns Nothing
- Test incrementally: Build path step by step
- Verify data structure: Query with empty path or root property first
- Check syntax: Ensure brackets and dots are correct
- Try wildcards: Use
*to see what's available
Edit Doesn't Work
- Query first: Verify path matches
- Check data type: Ensure value type matches
- Review backup: Compare before/after
- Validate JSON: Ensure file is valid
Transform Fails
- Check script syntax: Ensure TypeScript is valid
- Test function: Ensure function exported
- Handle edge cases: Check for null/undefined
- Review error message: TypeScript errors are specific
Examples by Use Case
API Response Processing
Extract user emails:
data.users[*].emailFilter active accounts:
Use a transform script for filtering:
export default (data: any) => {
return data.data.users.filter(u => u.status === "active" && u.verified);
};Configuration Updates
Update API endpoint:
Operation: set
Path: config.apiEndpoint
Value: "https://api.example.com"Enable feature flag:
Use a transform script for conditional updates:
export default (data: any) => {
const feature = data.features.find(f => f.name === "newFeature");
if (feature) feature.enabled = true;
return data;
};Data Migration
Transform user format:
export default (data: any) => ({
version: "2.0",
users: data.users.map((u: any) => ({
userId: u.id,
profile: {
name: u.name,
email: u.email,
},
metadata: {
createdAt: u.created,
active: u.status === "active",
}
}))
});Reference these patterns when helping users with JSON manipulation tasks. Always suggest the safest approach (query → dry-run → validate → execute) for destructive operations.