This question already has an answer here:
这个问题在这里已有答案:
- Swift 4 JSON Decodable with multidimensional and multitype array 5 answers
Swift 4 JSON可解码,具有多维和多样本数组5个答案
I have a Codable struct that is used to decode incoming JSON. Unfortunately, sometimes one of its key's value is a string, and sometimes it is a float. I was able to cobble a couple of do/try/catch blocks below to get it to work, but is there a better way to handle this?
我有一个Codable结构,用于解码传入的JSON。不幸的是,有时它的一个键的值是一个字符串,有时它是一个浮点数。我能够在下面拼凑一些do / try / catch块来使它工作,但是有更好的方法来处理它吗?
struct Project: Codable {
public let version: Float
init(from decoder: Decoder) throws {
var decodedVersion: Float = 1.0
do {
decodedVersion = try values.decode(Float.self, forKey: .version)
} catch {
do {
if let inVersion = try Float(values.decode(String.self, forKey: .version)) {
decodedVersion = inVersion
}
} catch {
throw error
}
}
version = decodedVersion
}
}
1 个解决方案
#1
17
If in your JSON the value associated to a key can be sometimes a Float
and sometimes a String
(besides fixing this error on the backend ????) you could follow this approach.
如果在您的JSON中,与键关联的值有时可能是Float,有时也是String(除了在后端修复此错误????)之外,您可以遵循此方法。
Let's say this is your "funny" JSON
让我们说这是你的“搞笑”JSON
let data = """
[
{
"magicField": "one"
},
{
"magicField":1
}
]
""".data(using: .utf8)!
Good, how can we elegantly represent this kind of data in Swift?
好,我们如何在Swift中优雅地表示这种数据?
struct Element:Decodable {
let magicField: ???
}
We want magicField
to always have a value, sometimes a Float
and sometimes a String
.
我们希望magicField总是有一个值,有时候是Float,有时候是String。
We can solve this with Quantum Mechanics... or with an Enum ????
Let's define this type
我们来定义这种类型
enum QuantumValue: Decodable {
case float(Float), string(String)
init(from decoder: Decoder) throws {
if let float = try? decoder.singleValueContainer().decode(Float.self) {
self = .float(float)
return
}
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
throw QuantumError.missingValue
}
enum QuantumError:Error {
case missingValue
}
}
As you can see a value of type QuantumValue
can hold a Float
or a String
. Always 1 and exactly 1 value.
如您所见,QuantumValue类型的值可以包含Float或String。始终为1且正好为1。
Element
We can now define the general element of our JSON
我们现在可以定义JSON的一般元素
struct Element:Decodable {
let magicField: QuantumValue
}
Decoding
That's it. Let's finally decode the JSON.
而已。让我们最终解码JSON。
if let elms = try? JSONDecoder().decode([Element].self, from: data) {
print(elms)
}
Result
[
Element(magicField: QuantumValue.string("one")),
Element(magicField: QuantumValue.float(1.0))
]
#1
17
If in your JSON the value associated to a key can be sometimes a Float
and sometimes a String
(besides fixing this error on the backend ????) you could follow this approach.
如果在您的JSON中,与键关联的值有时可能是Float,有时也是String(除了在后端修复此错误????)之外,您可以遵循此方法。
Let's say this is your "funny" JSON
让我们说这是你的“搞笑”JSON
let data = """
[
{
"magicField": "one"
},
{
"magicField":1
}
]
""".data(using: .utf8)!
Good, how can we elegantly represent this kind of data in Swift?
好,我们如何在Swift中优雅地表示这种数据?
struct Element:Decodable {
let magicField: ???
}
We want magicField
to always have a value, sometimes a Float
and sometimes a String
.
我们希望magicField总是有一个值,有时候是Float,有时候是String。
We can solve this with Quantum Mechanics... or with an Enum ????
Let's define this type
我们来定义这种类型
enum QuantumValue: Decodable {
case float(Float), string(String)
init(from decoder: Decoder) throws {
if let float = try? decoder.singleValueContainer().decode(Float.self) {
self = .float(float)
return
}
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
throw QuantumError.missingValue
}
enum QuantumError:Error {
case missingValue
}
}
As you can see a value of type QuantumValue
can hold a Float
or a String
. Always 1 and exactly 1 value.
如您所见,QuantumValue类型的值可以包含Float或String。始终为1且正好为1。
Element
We can now define the general element of our JSON
我们现在可以定义JSON的一般元素
struct Element:Decodable {
let magicField: QuantumValue
}
Decoding
That's it. Let's finally decode the JSON.
而已。让我们最终解码JSON。
if let elms = try? JSONDecoder().decode([Element].self, from: data) {
print(elms)
}
Result
[
Element(magicField: QuantumValue.string("one")),
Element(magicField: QuantumValue.float(1.0))
]