# How can I encode a struct to Data/binary?

**URL:** <https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652>\
**Category:** Using Swift\
**Tags:** decoding, encoding\
**Created:** [November 27, 2023, 11:42am UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652 "2023-11-27T11:42:31Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![danmihai](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/danmihai/32/21688_2.png) [@danmihai](https://forums.swift.org/u/danmihai)\
**Post date:** [November 27, 2023, 11:42am UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/1 "2023-11-27T11:42:31Z")

</div>

I know Swift has the `Codable` interface that allows a type be `encoded` or `decoded`. However, I only know of two encoders, namely `JSONEncoder` and `PropertyListEncoder`. What do I do if all I want to _binary_ (aka Data) encode?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [November 27, 2023, 12:05pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/2 "2023-11-27T12:05:54Z")

</div>

~~NSKeyedArchiver is you can stomach it.~~ (forget it, it won't work with structs).

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [November 27, 2023, 12:09pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/3 "2023-11-27T12:09:06Z")

</div>

If you need high performance encoding and decoding, I personally don't think `Codable` is a good fit. It doesn't support streaming, for example, and was built primarily with high-level serialization formats in mind, specifically JSON. Although, you'll gain an ability to switch to different encoders and decoders later if needed, if you build on top of `Codable`.

The most comprehensive set of functions that work with binary data are in Swift NIO's [`ByteBuffer`](https://swiftpackageindex.com/apple/swift-nio/2.62.0/documentation/niocore/bytebuffer). Those handle endianness, bit width, and alignment correctly for you on all platforms, and I recommend relying on it (or something similar) instead of using `withUnsafeBytes` directly on your own.

---

<div class="post-metadata">

**Author:** ![finestructure](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/finestructure/32/34879_2.png) [@finestructure](https://forums.swift.org/u/finestructure)\
**Post date:** [November 27, 2023, 12:45pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/4 "2023-11-27T12:45:06Z")

</div>

I haven't used it in earnest beyond playing around with it in a playground, but Paul Kraft's "DataKit" looks very interesting and might be useful for your purposes:

> **[DataKit – Swift Package Index](https://swiftpackageindex.com/QuickBirdEng/DataKit)**
>
> DataKit by QuickBird on the Swift Package Index – A Swift library to easily read and write binary formatted data using a modern, declarative interface.

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [November 27, 2023, 2:42pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/5 "2023-11-27T14:42:01Z")

</div>

It's great to see more packages appearing that address the need for binary serialization!

I see that it uses result builders, and I'd like to warn that for more complex model types I found that to be a major disadvantage when debugging and maintaining the serialization code.

One can't simply put a breakpoint at a result builder element to examine serialization input or output, which is the consequence of how result builders work. Result builders are usually evaluated at a different point in time than your serialization code, and they express logic at a certain level of indirection, which makes it hard to debug state at serialization time.

IMO macros are a much better fit for this, but I'm not aware of libraries exploring that space yet.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [November 27, 2023, 3:14pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/6 "2023-11-27T15:14:08Z")

</div>

> [@danmihai](#):
>
> However, I only know of two encoders, namely `JSONEncoder` and `PropertyListEncoder`.

BTW, is there a good and concise example of making a custom Encoder / Decoder?

I can quickly cook a very simple one that encodes, say, an Int or a String, but struggle with a more complex one that encodes a struct of multiple fields.

* * *

Edit: found [this one](https://github.com/lantua/CommonCoding/tree/master) from @Lantua but it's probably good to be used "as is" rather than an educational source how to make one. Will try to carve it down to a minimal educational example later on.

---

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [November 27, 2023, 4:48pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/7 "2023-11-27T16:48:50Z")

</div>

[XMLCoder](https://github.com/CoreOffice/XMLCoder) is one example, but after maintaining it in the past, I can say that `Codable` is suitable mainly for serialization formats that are strictly tree-like. XML is not one of those with its choice of coding as an attribute or an element, which makes things quite complicated and slow as a consequence, a lot of branching for these coding decisions has to be done dynamically at run time. If I were developing XMLCoder from scratch for Swift 5.9 I'd go with macros, skipping the current implementation of `Codable` altogether.

This could also be the case for the binary format that the OP would be using, same warning applies.

---

<div class="post-metadata">

**Author:** ![Jae](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jae/32/19660_2.png) [@Jae](https://forums.swift.org/u/Jae)\
**Post date:** [November 28, 2023, 7:22am UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/8 "2023-11-28T07:22:38Z")

</div>

I have used BSON with Codable as serialization method for binary data before, and if I need to do something along the line again I might go with ProtoBuf depending on the use case.

---

<div class="post-metadata">

**Author:** ![pbodsk](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pbodsk/32/32881_2.png) [@pbodsk](https://forums.swift.org/u/pbodsk)\
**Post date:** [November 28, 2023, 2:38pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/9 "2023-11-28T14:38:33Z")

</div>

Some years ago Mattt Thomson did a series of books about advanced topics in Swift called Flight School.

The first one was about [codable](https://flight.school/books/codable/) and in the final chapter he made a custom [`MessagePack`](https://msgpack.org) encoder.

The book is free now so maybe that can help you get an idea of what it takes to write a custom Encoder/Decoder 😄

---

<div class="post-metadata">

**Author:** ![jeremy](https://avatars.discourse-cdn.com/v4/letter/j/82dd89/32.png) [@jeremy](https://forums.swift.org/u/jeremy)\
**Post date:** [November 28, 2023, 5:05pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/10 "2023-11-28T17:05:21Z")

</div>

PropertyListEncoder can save binary data (as well as XML) and works well with structs. You need to do extra work for classes if you also use inheritance, but it's not so difficult. I really like Codable.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [November 29, 2023, 12:10am UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/11 "2023-11-29T00:10:11Z")

</div>

> [@danmihai](#):
>
> What do I do if all I want to _binary_ (aka Data) encode?

JSONEncoder returns Data... 😉

On a serious note, are you after encoding speed, decoding speed, encoded size, the desired "obfuscated" encoded representation, round trip (bit-for-bit) fidelity, key order stability, all or some of these, or something else altogether?

* * *

For example JSONEncoder can't roundtrip float values bit for bit:

```swift
let x = Float(-0.0)
let data = try! JSONEncoder().encode(x)
print(String(data: data, encoding: .ascii)!) // -0
let y = try! JSONDecoder().decode(Float.self, from: data)
print(x == y ? "x == y" : "x != y") // x == y
print(x.bitPattern == y.bitPattern ? "x.bitPattern == y.bitPattern" : "x.bitPattern != y.bitPattern") // x.bitPattern != y.bitPattern
print(String(x.bitPattern, radix: 2)) // 10000000000000000000000000000000
print(String(y.bitPattern, radix: 2)) // 0

```

Ditto (actually worse) for NaN, Inf and subnormals.

So if bit for bit roundtrip fidelity is important you'd need to choose among coders that preserve it.

---

<div class="post-metadata">

**Author:** ![Simon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/simon/32/11408_2.png) [@Simon](https://forums.swift.org/u/Simon)\
**Post date:** [December 4, 2023, 7:53pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/12 "2023-12-04T19:53:06Z")

</div>

I was looking for something like this a year ago, Thanks for the link

---

<div class="post-metadata">

**Author:** ![danmihai](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/danmihai/32/21688_2.png) [@danmihai](https://forums.swift.org/u/danmihai)\
**Post date:** [December 13, 2023, 9:45pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/13 "2023-12-13T21:45:53Z")

</div>

Thanks! This was what I was looking for:

```swift
let encoder = PropertyListEncoder()
encoder.outputFormat = .binary

```

I wanted to send objects via the network and deserialize them at the opposite path.

---

<div class="post-metadata">

**Author:** ![danmihai](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/danmihai/32/21688_2.png) [@danmihai](https://forums.swift.org/u/danmihai)\
**Post date:** [December 13, 2023, 9:49pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/14 "2023-12-13T21:49:04Z")

</div>

Ah, ok, and when I decode, it decodes back to the actual type. Lol! My entire life was a lie! I was operating under the impression it encodes to string or something.

---

<div class="post-metadata">

**Author:** ![carlynorama](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/carlynorama/32/27072_2.png) [@carlynorama](https://forums.swift.org/u/carlynorama)\
**Post date:** [March 6, 2024, 10:34pm UTC](https://forums.swift.org/t/how-can-i-encode-a-struct-to-data-binary/68652/15 "2024-03-06T22:34:59Z")

</div>

I quite liked [Routing with Codable – Encoding - Swift Talk - objc.io](https://talk.objc.io/episodes/S01E348-routing-with-codable-encoding)

I used it as foot hold to work on my own which is very much not heading towards being concise:

> **[How do custom Encoder's work?](https://www.whynotestflight.com/excuses/how-do-custom-encoders-work/)**
>
> A list of distractions

 ![Encoders_URI](https://global.discourse-cdn.com/swift/original/3X/3/0/303aaf27fe7f4cdfdbbe6c32d0645d7313ed7b1c.png)
