7

The code below works in Xcode 9.2 (Swift 4.0) but gives an error in Xcode 9.3 (Swift 4.1).

let dict: [String: Any] = [
    "status_code": 5,
    "status_message": "message"
]

let data = try! JSONEncoder().encode(dict)
                           // ^  generic parameter 'T' could not be inferred

I've tried making the dictionary [String: Encodable], and using a typealias to both dictionary types, with the same results. Swift doesn't let you specify the type in a generic call, so that gives a compiler error. What should this look like in Swift 4.1?

Dov
  • 15,530
  • 13
  • 76
  • 177
  • If you are looking for a solution then you should use a `Struct` instead of a `Dictionary`. – Luca Angeletti Apr 11 '18 at 12:36
  • @LucaAngeletti I do use a struct for my actual code. This is in a unit test where I'm constructing an atypical response, so I wanted to keep it loosely typed. I could define an ad-hoc struct in the function if I needed to, but I'd like to use a dictionary if possible – Dov Apr 11 '18 at 20:34
  • 1
    `Encodable` is a protocol, not a type. – Mike Taverne Apr 12 '18 at 05:31

1 Answers1

3

Is Dictionary Encodable?

In Swift 4.1 a Dictionary<Key, Value> conforms to Encodable only if Key and Value are Encodable themselves.

Examples of Encodable(s) dictionaries

[String:Int]
[String:String]
[String:Double]

Example of non Encodable(s) dictionaries

[String:Any]
[String:UIView]

So, how can you solve your problem?

Struct

Using a model value is probably the best solution

struct Status: Codable {
    let statusCode: Int
    let statusMessage: String
}

let status = Status(statusCode: 45, statusMessage: "message")
let data = try? JSONEncoder().encode(status)
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • 2
    But if that's the only reason, then why doesn't `[String: Encodable]` work? – Dov Apr 11 '18 at 20:32
  • 1
    @Dov Encodable isn't a concrete type so it can't be used – Jeremiah Jun 12 '18 at 14:45
  • @Jeremiah Thanks, I guess I didn't find it obvious that the values in a dictionary have to have a concrete type – Dov Jun 12 '18 at 19:16
  • 1
    How would you handle a dynamic list of properties in this scenario? For example what if the statusMessage above wasn't required? With a dictionary, you'd simply leave it out but I don't see how that's possible in a struct. – hocker Mar 30 '19 at 09:54