filter_var($value, FILTER_VALIDATE_BOOL), 'int' => $value === null || $value === '' ? null : (int) $value, 'float' => $value === null || $value === '' ? null : (float) $value, 'json' => is_array($value) ? $value : (json_decode((string) $value, true) ?: []), 'image_path' => is_string($value) ? trim($value) : null, default => $value === null ? null : trim((string) $value), }; } public static function serialize(mixed $value): ?string { if ($value === null) { return null; } if (is_bool($value)) { return $value ? '1' : '0'; } if (is_array($value)) { return json_encode($value, JSON_UNESCAPED_SLASHES); } return (string) $value; } public static function deserialize(?string $value, string $type): mixed { if ($value === null) { return null; } return match ($type) { 'bool' => $value === '1', 'int' => (int) $value, 'float' => (float) $value, 'json' => json_decode($value, true) ?: [], default => $value, }; } public static function isUnchanged(mixed $oldValue, mixed $newValue): bool { return self::serialize($oldValue) === self::serialize($newValue); } }