MessagePack is an efficient binary serialization format that lets you exchange data among multiple languages like JSON but in a more compact and faster form. Small integers can be encoded in a single byte, and short strings require only a prefix plus the original byte array. MessagePack implementations are available in various languages (see the list on https://msgpack.io). For the specification, see https://github.com/msgpack/msgpack/blob/master/spec.md.
MessagePack implementation for Swift
This repository provides a MessagePack encoder and decoder for Swift that integrates with the Swift Codable API.
- Encodes and decodes Swift types using the
Codableprotocol - Seamless integration with Swift Package Manager
- Compatible with Swift 6
- Works on Linux, iOS, and macOS
- Published under the MIT License
import SwiftMsgpack
struct Coordinate: Codable {
let latitude: Double
let longitude: Double
}
struct Landmark: Codable {
let name: String
let foundingYear: Int
let location: Coordinate
}
let input = Landmark(
name: "Mojave Desert",
foundingYear: 0,
location: Coordinate(
latitude: 35.0110079,
longitude: -115.4821313
)
)
let encoder = MsgPackEncoder()
let decoder = MsgPackDecoder()
let data = try! encoder.encode(input)
let out = try! decoder.decode(Landmark.self, from: data)
let any = try! decoder.decode(AnyCodable.self, from: data)
print([UInt8](data))
// [131, 164, 110, 97, 109, 101, 173, 77, 111, 106,
// 97, 118, 101, 32, 68, 101, 115, 101, 114, 116,
// 172, 102, 111, 117, 110, 100, 105, 110, 103, 89,
// 101, 97, 114, 0, 168, 108, 111, 99, 97, 116,
// 105, 111, 110, 130, 168, 108, 97, 116, 105, 116,
// 117, 100, 101, 203, 64, 65, 129, 104, 180, 245,
// 63, 179, 169, 108, 111, 110, 103, 105, 116, 117,
// 100, 101, 203, 192, 92, 222, 219, 61, 61, 120,
// 49]
print(out)
// Landmark(
// name: "Mojave Desert",
// foundingYear: 0,
// location: example.Coordinate(
// latitude: 35.0110079,
// longitude: -115.4821313
// )
// )
print(any)
// AnyCodable(
// [
// AnyCodable("foundingYear"): AnyCodable(0),
// AnyCodable("name"): AnyCodable("Mojave Desert"),
// AnyCodable("location"): AnyCodable(
// [
// AnyCodable("longitude"): AnyCodable(-115.4821313),
// AnyCodable("latitude"): AnyCodable(35.0110079),
// ]
// ),
// ]
// )MsgPackDecoder has an opt-in lazy mode that defers walking the contents of MessagePack arrays and maps until the Codable target asks for them. Pass .lazyScan when constructing the decoder:
let decoder = MsgPackDecoder(options: .lazyScan)
let value = try decoder.decode(SparseStruct.self, from: largePayload)The result is bit-identical to the default eager mode; only the cost profile of decode(_:from:) changes.
When .lazyScan helps
- Decoding a small subset of fields from a large map. Picking 3 keys from a 1000-key payload measures roughly 91% lower wall clock and 99% fewer allocations than the eager path.
- Sparse
structtargets against dense maps scale similarly as the source grows (about 10% faster at size 10, around 90% at size 1000).
When the eager default is preferable
- Array payloads where every element is read. The per-element cursor allocation adds about 13% wall clock and 30% extra
malloccalls on[Item]x 1000. - Fully materialised dictionaries (
[String: String]), nested map-of-map round trips, andAnyCodableare within ±5% of eager — either mode is fine.
Safety
- The lazy IR borrows the lifetime of the
Datapassed todecode(_:from:). Do not retain the decoder or container objects past the call — the cursors hold raw pointers that are only valid while the decode call is on the stack. MsgPackDecoderis notSendable; do not share a single decoder across threads.
To use swift-msgpack in your Swift project, add it as a dependency in your Package.swift:
let package = Package(
// name, platforms, products, etc.
dependencies: [
// other dependencies
.package(url: "https://github.com/nnabeyang/swift-msgpack", from: "1.2.0"),
],
targets: [
.executableTarget(name: "<executable-target-name>", dependencies: [
// other dependencies
.product(name: "SwiftMsgpack", package: "swift-msgpack"),
]),
// other targets
]
)Add the following to your Podfile:
pod 'SwiftMessagePack'
swift-msgpack is published under the MIT License. See the LICENSE file for details.
swift-msgpack is a library of MessagePack encoder & decoder for Swift based on Codable, following the same design principles as Swift’s built-in JSON support.