Search code examples
jsonswiftcodabledecodable

How can I handle different types of JSON data with Codable?


struct Sample: Codable {
    let dataA: Info?

    enum CodingKeys: String, CodingKey {
        case dataA
    }

    enum Info: Codable {
        case double(Double)
        case string(String)

        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let x = try? container.decode(Double.self) {
                self = .double(x)
                return
            }
            if let x = try? container.decode(String.self) {
                self = .string(x)
                return
            }
            throw DecodingError.typeMismatch(Info.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Info"))
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case .double(let x):
                try container.encode(x)
            case .string(let x):
                try container.encode(x)
            }
        }
    }
}

So, I've got some data from server as JSON and converted for my model "Sample".

As you can see, Sample.data can be String or Double.

But I don't know how I can get dataA in other class.

let foodRate = dataFromServer.dataA.....?

What should I do for using dataA?


Solution

  • You can use a switch statement to extract the values

    switch dataFromServer.dataA {
    case .double(let number):
        print(number)
    case .string(let string):
        print(string)
    case .none:
        print("Empty")
    }