Attribution: This library is developed based on the approach and methodology from OpenAI's Node.js library, which itself vendors the Promplate partial-json-parser-js library. The test cases and parsing strategies are adapted from both the original @promplate implementation and @OpenAI's usage of it, ported to Swift with additional Swift-specific optimizations.
Special thanks to the @Promplate team for creating the original partial JSON parsing solution that inspired this Swift implementation.
A Swift library for parsing incomplete or streaming JSON data. Perfect for handling truncated JSON responses, streaming APIs, or progressive JSON parsing scenarios.
- ✅ Parse incomplete JSON strings that are truncated or still being streamed
- ✅ Configurable parsing options to control which types can be partial
- ✅ Support for all JSON types: objects, arrays, strings, numbers, booleans, and null
- ✅ Handle special numeric values:
Infinity,-Infinity, andNaN - ✅ Comprehensive error handling with detailed error messages
- ✅ Zero dependencies beyond Foundation
- ✅ Full test coverage
- ✅ Swift 6 compatible
Add the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/itruf/PartialJSON.git", from: "0.0.2")
]Then add PartialJSON as a dependency to your target:
targets: [
.target(
name: "YourTarget",
dependencies: ["PartialJSON"]
)
]- In Xcode, select File → Add Package Dependencies
- Enter the repository URL:
https://github.com/itruf/PartialJSON.git - Select your desired version and add to your project
import PartialJSON
// Parse incomplete JSON with default options
let incompleteJSON = "[1, 2, 3"
let result = try PartialJSON.parse(incompleteJSON)
// Result: [1, 2, 3]
// Parse incomplete object
let partialObject = "{\"name\": \"John\", \"age\""
let obj = try PartialJSON.parse(partialObject)
// Result: ["name": "John"]Control which types can be parsed when incomplete:
// Allow all types to be partial
let result = try PartialJSON.parse("[1, 2, 3.", options: .all)
// Result: [1, 2, 3.0]
// Allow only arrays and objects to be partial
let result = try PartialJSON.parse("[1, 2, 3", options: .collections)
// Result: [1, 2, 3]
// Custom options combination
let customOptions: PartialJSONOptions = [.array, .object, .string]
let result = try PartialJSON.parse("{\"text\": \"incompl", options: customOptions)
// Result: ["text": "incompl"]// Individual options
.string // Allow partial strings
.number // Allow partial numbers
.array // Allow partial arrays
.object // Allow partial objects
.null // Allow partial null (e.g., "nu" → null)
.boolean // Allow partial booleans (e.g., "tr" → true)
.nan // Allow partial NaN
.infinity // Allow partial Infinity
.negativeInfinity // Allow partial -Infinity
// Convenience combinations
.allInfinity // Both positive and negative infinity
.special // null, boolean, infinity, nan
.atomic // string, number, special
.collections // array, object
.all // Everything
.allExceptNumbers // Everything except numbers (default)The library provides two types of errors:
do {
let result = try PartialJSON.parse(jsonString)
} catch let error as PartialJSONError {
// JSON is incomplete in a way not allowed by options
print("Incomplete JSON: \(error.message) at position \(error.position)")
} catch let error as MalformedJSONError {
// JSON has invalid syntax
print("Invalid JSON: \(error.message) at position \(error.position)")
}class StreamingParser {
private var buffer = ""
private let options: PartialJSONOptions = .all
func append(_ chunk: String) -> Any? {
buffer += chunk
do {
return try PartialJSON.parse(buffer, options: options)
} catch {
// Not yet complete, wait for more data
return nil
}
}
}// Useful for showing partial results while loading
func loadProgressively(from chunks: [String]) {
var accumulated = ""
for chunk in chunks {
accumulated += chunk
if let partial = try? PartialJSON.parse(accumulated, options: .collections) {
// Update UI with partial results
updateDisplay(with: partial)
}
}
}// Handle potentially truncated API responses
func handleAPIResponse(_ data: Data) throws -> Any {
guard let jsonString = String(data: data, encoding: .utf8) else {
throw APIError.invalidEncoding
}
// Try to parse even if response was truncated
return try PartialJSON.parse(jsonString, options: .allExceptNumbers)
}- The library uses efficient
String.Indexoperations for optimal performance - First attempts to parse as complete JSON using native
JSONSerialization - Falls back to partial parsing only when necessary
- Minimal memory overhead with streaming-friendly design
- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+
- Swift 5.5+
- Xcode 13.0+
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Run the test suite:
swift testOr in Xcode:
- Press
Cmd+Uto run all tests
Ivan Trufanov
- Inspired by the need for robust JSON parsing in streaming scenarios
- Built with Swift's powerful string handling capabilities