How can I use Swift’s Codable to encode into a dictionary?

If you don’t mind a bit of shifting of data around you could use something like this:

extension Encodable {
  func asDictionary() throws -> [String: Any] {
    let data = try JSONEncoder().encode(self)
    guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
      throw NSError()
    }
    return dictionary
  }
}

Or an optional variant

extension Encodable {
  var dictionary: [String: Any]? {
    guard let data = try? JSONEncoder().encode(self) else { return nil }
    return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
  }
}

Assuming Foo conforms to Codable or really Encodable then you can do this.

let struct = Foo(a: 1, b: 2)
let dict = try struct.asDictionary()
let optionalDict = struct.dictionary

If you want to go the other way(init(any)), take a look at this Init an object conforming to Codable with a dictionary/array

Leave a Comment