1

Why does code print with surrounding parenthesis and with the prefix int or string? For example:

code: string("Gate: 2312231")

How can I just have it print code: 2312231 and nothing more? Try the following code in Playgrounds to see the the printed values. I appreciate the help, let me know if there are any questions.

let data = """
[
  {
    "date": "2022-05-04",
    "code": 122312,
    "notes": "Take keys"
  },
  {
    "date": "2022-05-04",
    "code": "Gate: 2312231",
    "notes": "Take Box"
  }
]
""".data(using: .utf8)!

enum Code: Decodable {
    case int(Int)
    case string(String)
}

struct Item: Decodable {
    var date: Date
    var code: Code
    var notes: String

    enum CodingKeys: String, CodingKey {
        case date, code, notes
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.date = try container.decode(Date.self, forKey: .date)
        self.notes = try container.decode(String.self, forKey: .notes)

        if let value = try? container.decode(Int.self, forKey: .code) {
            self.code = .int(value)
        } else if let value = try? container.decode(String.self, forKey: .code) {
            self.code = .string(value)
        } else {
            let context = DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unable to decode value for `code`")
            throw DecodingError.typeMismatch(Code.self, context)
        }
    }
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

let items = try! decoder.decode([Item].self, from: data)

for item in items {
    print("date: \(item.date.description)")
    print("code: \(item.code)")
    print("notes: \(item.notes)")
    print()
}
John
  • 965
  • 8
  • 16
  • Why did you expect 2312231 only? Shouldn't "Gate: " also be included? That whole thing is the entire string, isn't it? – Sweeper May 05 '22 at 19:41
  • Yes apologies, the desired result is `code: Gate: 2312231` – John May 05 '22 at 19:44
  • It's printing the `int` or `string` prefix because your `Code` type is an enum with associated values, and `int` and `string` are the name of its cases. If you want to print just the int, or just the string, then you need to read those associated values out and use them directly. – Alexander May 05 '22 at 19:45
  • Understood, how can the associated values be read out and used? – John May 05 '22 at 19:46
  • Not related to your question but your DateFormatter is very error prone – Leo Dabus May 05 '22 at 19:54
  • Btw you are force unwrapping the try keyword. If anything goes wrong (and it will for sure) it will crash your app. You should always handle the errors thrown. – Leo Dabus May 05 '22 at 19:57
  • @StephanieSmith Check out https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html#ID148 – Alexander May 05 '22 at 20:13
  • I'm not sure this de-duplicatation is accurate. The solution here is to probably to unwrap these values and handle them properly, not just to override `description` in a way that plasters over the mistake – Alexander May 05 '22 at 20:27
  • Can you please show an example, I would really appreciate it – John May 05 '22 at 20:32

0 Answers0