name: serialization-review
description: Review JSON serialization for scenes, prefabs, and components. Use when: (1) implementing serializable components, (2) debugging save/load failures, (3) adding asset types, (4) reviewing serialization code, (5) investigating data corruption, (6) implementing JsonConverters.
Serialization Review
Overview
This skill audits JSON serialization implementation to ensure scenes, prefabs, and components serialize/deserialize correctly, maintain version compatibility, handle resource references properly, and follow established serialization patterns.
Table of Contents
When to Use
Invoke this skill when:
- Adding new serializable components
- Debugging scene save/load issues
- Implementing new asset types (prefabs, animations, tilemaps)
- Refactoring component data structures
- Versioning serialization format
- Questions about custom JsonConverter implementation
- Investigating data corruption or missing data after load
Serialization Architecture
SceneSerializer
Location: Engine/Scene/Serializer/SceneSerializer.cs
Responsibilities:
- Serialize/deserialize entire scene to/from JSON
- Handle entity hierarchy and component serialization
- Manage custom converters and serialization options
Key Methods: Serialize(Scene, path), Deserialize(path)
Custom Converters
Location: Engine/Scene/Serializer/
Existing Converters:
Vector2Converter, Vector3Converter, Vector4Converter
TileMapComponentConverter
- Component-specific converters for complex types
Serialization Patterns
1. JsonIgnore for Runtime Data
Pattern: Use [JsonIgnore] for runtime-only data
public class RigidBody2DComponent
{
public BodyType Type { get; set; } = BodyType.Dynamic;
public float Mass { get; set; } = 1.0f;
public bool FixedRotation { get; set; } = false;
[JsonIgnore]
public Body? RuntimeBody { get; set; }
[JsonIgnore]
public World? RuntimeWorld { get; set; }
}
Why?: Runtime objects (physics bodies, loaded meshes, textures) should not be serialized - they're recreated at runtime.
2. Resource Path Serialization
Pattern: Store paths, not loaded resources
public class SpriteRendererComponent
{
public string TexturePath { get; set; } = string.Empty;
public Vector4 Color { get; set; } = Vector4.One;
[JsonIgnore]
public Texture? LoadedTexture { get; set; }
}
if (!string.IsNullOrEmpty(sprite.TexturePath))
{
try
{
sprite.LoadedTexture = textureFactory.LoadTexture(sprite.TexturePath);
}
catch (FileNotFoundException)
{
logger.Warn($"Missing texture: {sprite.TexturePath}");
sprite.LoadedTexture = textureFactory.GetDefaultTexture();
}
}
3. Custom Converter for Complex Types
When Needed:
- Custom serialization format or optimized JSON structure
- Backward compatibility with breaking changes
- Complex type handling (vectors, GUIDs, nested structures)
Review Checklist
When reviewing serialization implementation, verify:
1. Runtime Data Exclusion
2. Resource References
3. Circular References
4. Version Compatibility
5. Custom Converters
Review Output Format
Report findings as:
Issue: [Serialization problem description]
Component: [Component class name]
Location: [File path and line number]
Problem: [What will break or serialize incorrectly]
Fix: [Code change with before/after]
Priority: [Critical/High/Medium/Low]
Example Report
Issue: Runtime physics body being serialized
Component: RigidBody2DComponent
Location: Engine/Scene/Components/RigidBody2DComponent.cs:45
Problem: RuntimeBody property will serialize the entire Box2D body object, causing massive JSON files and deserialization failures (Box2D objects aren't JSON-serializable)
Fix:
public Body? RuntimeBody { get; set; }
[JsonIgnore]
public Body? RuntimeBody { get; set; }
Priority: Critical
Examples
For detailed guidance and comprehensive examples:
Complete JsonConverter implementations with:
- Full AnimationComponent converter with error handling
- Vector3, GUID, and common type converters
- Registration and testing patterns
- Best practices for symmetric Read/Write methods
Anti-pattern catalog with before/after fixes:
- Runtime objects not marked [JsonIgnore]
- Loaded resources instead of paths
- Missing default values for new fields
- Circular references in entity hierarchy
- Platform-specific path separators
- Asymmetric converter implementations