(Apologies for the re-post. We thought it best to create a new topic for increased visibility since some might not be following the original thread.)
Hello again Swift Community!
Here we are, almost a full year after my “future of serialization & deserialization APIs” post. I’ve spent a lot of time since then working to make this into a reality, and I’m happy to announce that I have something concrete for you to try out!
Please take a look at GitHub - swiftlang/swift-foundation at experimental/new-codable · GitHub ! You’ll find therein the core components of this design exposed in a new target temporarily called NewCodable:
-
CommonEncodableandCommonDecodableprotocols. These are the format-agnostic protocols that are the closest relatives toEncodableandDecodable, but are designed in such a way that avoids many of the performance limitations of the latter. -
CommonEncoderandCommonDecoderprotocols. Similarly, these are format-agnostic protocols for encoders and decoders in the same vein asEncoderandDecoder, but with a better design. -
JSONEncodableandJSONDecodableprotocols. These are shaped similarly to theirCommoncounterparts, but with modifications that are specific to JSON, including certain performance optimizations. -
JSONDecoderProtocol(naming discrepancy acknowledged, but I can’t name itJSONDecoder!) with concrete implementationsJSONParserDecoderandJSONPrimitiveDecoder. -
JSONDirectEncoder(no protocol here yet, despite room for an alternativeJSONElementEncoderto mirrorJSONElementDecoder. Will discuss elsewhere.) -
“Top-level”
NewJSONEncoderandNewJSONDecoder(names TBD, since I similarly can’t name themJSONEncoderandJSONDecoder!) -
JSONElementand other supporting protocols and types.
Please note that swift-foundation is acting as a convenient and temporary holding place for this project. We’ll evolve it on this branch for a while as we iterate on it and refine it. We’ll determine what the final locations for the various pieces will be as we get closer to its productization.
This is still very much a work in progress! Please excuse our dust! You’ll find plenty of TODOs scattered throughout, somewhat haphazard inlining of functions, and probably plenty of bugs and issues. I have ported over many of the tests from the existing JSON Codable-based unit tests in swift-foundation, but a few of those are still failing for various reasons.
Despite all of that, I hope some of you get an opportunity to take a look and try adopting the protocols use the new encoders/decoders with some of your own types. Let us know about any pain points or friction you’re experiencing with the API.
There are some benchmarks included (still of bespoke infrastructure) which are quite promising. When decoding twitter.json, I personally observe that JSONDecodable and JSONParserDecoder provide a throughput improvement of approximately 6x over Decodableand JSONDecoder! I hope that with community involvement we’ll be able to improve both overall quality and performance to even higher levels.
To try using the “New Codable”, change your swift-foundation dependency to
.package(
url: "https://github.com/apple/swift-foundation.git",
branch: "experimental/new-codable"
)
and import NewCodable. Swift 6.3 is required.
To run the tests, execute the following in a swift-foundation checkout of this branch:
swift test --filter NewCodableTests
To run the benchmarks:
swift test --configuration release --filter NewCodableBenchmarks
Please take note of this rough roadmap that lies ahead for this project:
-
Finalize the
Common*protocols -
Finalize the
JSON*APIs -
Support Embedded Swift
-
Add support for XML and Binary Property List
-
Design and implement macros for
@JSONCodable,@PropertyListCodable,@CommonCodable, and even@Codable. -
Publish a library for owners of other format-specific protocols to facilitate development of their own
@<Format>Codablemacros that use common patterns established by the above macros.
If you see an issue or have a question, please speak up! I’ll be happy to try to address any concerns. Feel free to create an Issue on the swift-foundation GitHub tagged with the new-codable label. If you want to fix something, feel free to create a Pull Request against this experimental/new-codable branch, again tagged with the new-codable label.
To help drive community involvement towards finalizing milestones #1 and #2, I will be starting threads that discuss different aspects of the prototype’s API with explanations of why that design was chosen, challenges we’re still facing, and alternatives we’ve considered. I hope to get your focused feedback in those discussions.
As a footnote, while the inspiration for the origins of this project was heavily rooted in Rust serde, I found that the general shape of the musli crate was a better fit for adapting to Swift. (Though, it’s quite a bit more reliant on closures with inout arguments rather than consumed and reborrowed mutable references. I’ll start a discussion about that as well.)