I'm currently working with Codable
types in my project and facing an issue.
struct Person: Codable
{
var id: Any
}
id
in the above code could be either a String
or an Int
. This is the reason id
is of type Any
.
I know that Any
is not Codable
.
What I need to know is how can I make it work.
First of all you can define a type that can be decoded both from a String
and Int
value.
Here it is.
enum QuantumValue: Decodable {
case int(Int), string(String)
init(from decoder: Decoder) throws {
if let int = try? decoder.singleValueContainer().decode(Int.self) {
self = .int(int)
return
}
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
throw QuantumError.missingValue
}
enum QuantumError:Error {
case missingValue
}
}
Now you can define your struct like this
struct Person: Decodable {
let id: QuantumValue
}
That's it. Let's test it!
id
is String
let data = """
{
"id": "123"
}
""".data(using: String.Encoding.utf8)!
if let person = try? JSONDecoder().decode(Person.self, from: data) {
print(person)
}
id
is Int
let data = """
{
"id": 123
}
""".data(using: String.Encoding.utf8)!
if let person = try? JSONDecoder().decode(Person.self, from: data) {
print(person)
}
This new paragraph should answer the questions from the comments.
If you want to compare a quantum value to an Int
you must keep in mind that a quantum value could contain an Int
or a String
.
So the question is: what does it mean comparing a String
and an Int
?
If you are just looking for a way of converting a quantum value into an Int
then you can simply add this extension
extension QuantumValue {
var intValue: Int? {
switch self {
case .int(let value): return value
case .string(let value): return Int(value)
}
}
}
Now you can write
let quantumValue: QuantumValue: ...
quantumValue.intValue == 123
This part to answer the comment left by @Abrcd18.
You can add this computed property to the Person
struct.
var idAsString: String {
switch id {
case .string(let string): return string
case .int(let int): return String(int)
}
}
And now to populate the label just write
label.text = person.idAsString
Hope it helps.