ANSCoder/CowCodable
Deterministic, production-safe JSON resilience for Swift using @CowResilient.
What It Solves
Real backend payloads frequently drift:
- Type mismatches (
"42"instead of42) - Partially corrupted arrays/dictionaries
- Missing keys vs explicit
null
CowCodable handles these cases explicitly while avoiding silent corruption.
Design Principles
- Deterministic rescue
- No silent corruption
- No unsafe coercion
- Strong type safety
- Configurable null strategy
Supported Types
CowResilient<Value> supports deterministic rescue for:
String,Int,Double,Float,Bool,Character- Arrays of supported primitive types
- Nested arrays of supported primitive types
[String: SupportedPrimitive]- Nested dictionaries of supported primitive values
Conversion Rules Summary
| From JSON | To Swift | Strict | Permissive | |----------|----------|--------|------------| | Int | String | Yes | Yes | | Double | String | Yes | Yes | | Bool | String | Yes | Yes | | Numeric String | Int | Yes ("42") | Yes ("42", "1e3" when integral) | | Double | Int | Yes (integral only) | Yes (integral only) | | Numeric String | Double | Yes | Yes | | Numeric String | Float | Yes | Yes (NaN/Infinity allowed) | | Bool-like String | Bool | Yes | Yes | | Single-character String | Character | Yes | Yes | | Integer Unicode scalar | Character | No | Yes | | Scalar | [T] | No | Yes (single wrapped element) |
Ambiguous coercions always fail (12.3 -> Int, overflowed numeric conversions).
Strict vs Permissive Modes
CowConfiguration.defaultRescueStrategy = StrictRescueStrategy.self
CowConfiguration.defaultRescueStrategy = PermissiveRescueStrategy.selfStrictRescueStrategy: minimal deterministic coercion.PermissiveRescueStrategy: broader deterministic coercion for known backend drift.
CowNullStrategy
CowConfiguration.defaultNullStrategy = .fail
CowConfiguration.defaultNullStrategy = .useDefault
CowConfiguration.defaultNullStrategy = .skipCowResilient explicitly distinguishes:
- Missing key
- Explicit
null - Invalid type
Deterministic Logging
CowCodable emits structured logs through CowLogger:
- rescued values
- skipped entries
- failures
Logs include coding paths and raw values for diagnostics and UI presentation.
Repository Layout
CowCodable/
βββ Package.swift
βββ README.md
βββ Sources/CowCodable/
β βββ Core/
β βββ Bridge/
β βββ Defaults/
β βββ Logging/
β βββ Extensions/
βββ Tests/CowCodableTests/
βββ Examples/
βββ docs/screenshots/
βββ DemoApp/CowCodableDemoApp/
βββ CowCodableDemoApp.xcodeproj
βββ CowCodableDemoApp/Requirements
- Swift 5.9+
- iOS 16.0+
- macOS 13.0+
- Xcode 15+
CowCodable uses modern Swift concurrency and type-safe rescue strategies.
Installation
Swift Package Manager
Using Xcode
- Open your project in Xcode.
- Go to File β Add Package Dependenciesβ¦
- Enter the repository URL: https://github.com/ANSCoder/CowCodable.git
- Select the latest version.
- Add the CowCodable library to your target.
Using Package.swift
Add CowCodable to your dependencies:
dependencies: [
.package(url: "https://github.com/ANSCoder/CowCodable.git", from: "1.0.0")
]Demo App
The repository includes a separate iOS SwiftUI demo app target:
- Project:
DemoApp/CowCodableDemoApp/CowCodableDemoApp.xcodeproj - Minimum iOS:
16.0 - Interface: SwiftUI (no storyboard)
Open and Run in Simulator
- Open
DemoApp/CowCodableDemoApp/CowCodableDemoApp.xcodeprojin Xcode. - Select the
CowCodableDemoAppscheme. - Choose an iOS 16+ simulator device.
- Build and run.
The app imports CowCodable as a local Swift package dependency from this repository root and does not duplicate SDK sources.
Presets and What They Demonstrate
Primitive Corruption: primitive type drift and deterministic rescue.Array Corruption: mixed arrays with rescued and skipped elements.Dictionary Corruption: value rescue and deterministic invalid entry dropping.Nested Complex: nested resilience across multiple levels.Null Edge Case: null/missing behavior under different null strategies.Overflow Case: deterministic overflow and non-finite numeric handling.Strict vs Permissive Case: side-by-side behavior change with identical input.
Strict vs Permissive in the Demo
Strictapplies minimal deterministic coercion.Permissiveallows additional deterministic conversions (for example scientific notation-to-int when integral, scalar-to-array wrapping, Unicode scalar character conversion).
Switching the segmented control changes only the configured rescue policy; input JSON stays unchanged so behavior differences are observable.
π± Demo App Preview
Main View
<p align="center"> <img src="docs/screenshots/demo-main.png" width="320"> </p>
Strict Mode
<p align="center"> <img src="docs/screenshots/demo-strict.png" width="320"> </p>
Permissive Mode
<p align="center"> <img src="docs/screenshots/demo-permissive.png" width="320"> </p>
Overflow Case
<p align="center"> <img src="docs/screenshots/demo-overflow.png" width="320"> </p>
Example Model
struct Profile: Codable {
@CowResilient var id: String = ""
@CowResilient var score: Double = 0
@CowResilient var flags: [Bool] = []
}Performance Characteristics
- O(1) direct primitive rescue
- O(n) array/dictionary rescue
- No reflection or runtime type hacks
Thread Safety
CowResilientis value-based andSendablewhenValueisSendable.CowConfigurationandCowLoggerare lock-protected.- Decode on background queues and update UI on main thread.
Limitations
- No rescue for arbitrary
Codableobject graphs via reflection - No ambiguous coercion
- No hidden mutation of invalid backend data
- No magic auto-fixes outside documented conversion rules
Quality Gates
The repository uses deterministic validation for both SDK and demo app:
swift buildswift testxcodebuild -project DemoApp/CowCodableDemoApp/CowCodableDemoApp.xcodeproj -scheme CowCodableDemoApp -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build
These checks run in CI at .github/workflows/ci.yml.
Code Style
This project enforces consistent formatting via:
.editorconfig(editor-level policy).swiftformat(SwiftFormat configuration)
Formatting is validated in CI.
License
CowCodable is released under the MIT License.
See the LICENSE file for details.
Package Metadata
Repository: ANSCoder/CowCodable
Stars: 0
Forks: 0
Open issues: 0
Default branch: main
Primary language: swift
License: MIT
Topics: codable, decoding, ios-swift, jsonparser, serialization, swift, swift-package-manager, xcode
README: README.md