0

This is similar to for example this question: How can I use Swift’s Codable to encode into a dictionary?, except that I want to specifically turn it into a [String: CustomStringConvertible] dictionary and I am not able to.

struct Model: Codable {
  let a: String
  let b: Int
}

let jsonData = try JSONEncoder().encode(Model(a: "a", b: 1))
let parameters = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments)
parameters as? [String: CustomStringConvertible] // nil

How can I make this work? This for example does work, which should work the same you'd think:

let dict: Any = ["a": "a", "b": 1]
dict as? [String: CustomStringConvertible] // ["a": "a", "b": 1]
Kevin Renskers
  • 5,156
  • 4
  • 47
  • 95
  • 1
    I am curious why you would need this? – Joakim Danielson Oct 13 '21 at 11:33
  • Because I need these dictionaries to be Equatable, which `[String: CustomStringConvertible]` is super handy for. And they fit the kind of data I'm working with, so win win :) – Kevin Renskers Oct 13 '21 at 13:57
  • Wouldn't it be easier to compare objects for equality instead of comparing dictionaries? `CustomStringConvertible` is maybe handy but it won't give always correct results. Sounds a bit like a javascripty solution. – Sulthan Oct 13 '21 at 14:01
  • Is that really a win win? 1 and "1" will be considered equal which isn't exactly true and a custom type (as value) that conforms to both Equatable and CustomStringConvertible will be compared using the latter protocol – Joakim Danielson Oct 13 '21 at 14:12
  • It's for HTTP endpoint parameters where it doesn't matter if we compare "1" and 1, and yeah there's a reason for all of this, which is hard to explain in just a simple SO question. – Kevin Renskers Oct 15 '21 at 12:13

1 Answers1

0

The trick is to first cast it to [String: AnyObject] and THEN to [String: CustomStringConvertible]:

struct Model: Codable {
  let a: String
  let b: Int
}

let jsonData = try JSONEncoder().encode(Model(a: "a", b: 1))
let parameters = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [String: AnyObject] as? [String: CustomStringConvertible]

Weird, but it works ‍♂️

Kevin Renskers
  • 5,156
  • 4
  • 47
  • 95