在 Swift 模型中解码数组(可解码)
Decoding an Array in a Swift model (Decodable)
我正在从 API 中检索 JSON,我想为我使用的每个端点创建一个模型。
所有端点都使用这种格式:
{
"id": "xxxxxx",
"result": {…},
"error": null
}
关键是:
id
总是一个字符串
error
可以是 null 或其中包含键的对象
result
可以是 null;对象或数组。
我遇到的问题是,在其中一个端点上,结果是数组数组:
{
"id": "xxxxxx",
"result": [
[
"client_id",
"name",
50,
"status"
]
],
"error": null
}
如您所见,我有数组数组,其中的值可以是 String 或 Int。
如何使用 Decodable 协议对其进行解码,然后根据其原始值将这些解码值用作 String 或 Int?
import Foundation
let string = """
{
"id": "xxxxxx",
"result": [
[
"client_id",
"name",
50,
"status"
]
],
"error": null
}
"""
struct Container: Codable {
let id: String
let result: [[Result]]
let error: String?
}
enum Result: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Result.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Result"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self)
}
}
let jsonData = string.data(using: .utf8)!
let container = try? JSONDecoder().decode(Container.self, from: jsonData)
print(container)
改进了@ArinDavoodian 的回答。
读取数据:
container?.result.first?.forEach { object in
switch object {
case let .integer(intValue):
print(intValue)
break
case let .string(stringValue):
print(stringValue)
break
}
}
一个简单的解决方案:
let yourInsideArray = container?.result.first!
for index in 0..<yourInsideArray.count {
let yourObjectInsideThisArray = yourInsideArray[i]
//do some
switch yourObjectInsideThisArray {
case let .integer(intValue):
print(intValue)
break
case let .string(stringValue):
print(stringValue)
break
}
}
我正在从 API 中检索 JSON,我想为我使用的每个端点创建一个模型。
所有端点都使用这种格式:
{
"id": "xxxxxx",
"result": {…},
"error": null
}
关键是:
id
总是一个字符串error
可以是 null 或其中包含键的对象result
可以是 null;对象或数组。
我遇到的问题是,在其中一个端点上,结果是数组数组:
{
"id": "xxxxxx",
"result": [
[
"client_id",
"name",
50,
"status"
]
],
"error": null
}
如您所见,我有数组数组,其中的值可以是 String 或 Int。
如何使用 Decodable 协议对其进行解码,然后根据其原始值将这些解码值用作 String 或 Int?
import Foundation
let string = """
{
"id": "xxxxxx",
"result": [
[
"client_id",
"name",
50,
"status"
]
],
"error": null
}
"""
struct Container: Codable {
let id: String
let result: [[Result]]
let error: String?
}
enum Result: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Result.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Result"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self)
}
}
let jsonData = string.data(using: .utf8)!
let container = try? JSONDecoder().decode(Container.self, from: jsonData)
print(container)
改进了@ArinDavoodian 的回答。
读取数据:
container?.result.first?.forEach { object in
switch object {
case let .integer(intValue):
print(intValue)
break
case let .string(stringValue):
print(stringValue)
break
}
}
一个简单的解决方案:
let yourInsideArray = container?.result.first!
for index in 0..<yourInsideArray.count {
let yourObjectInsideThisArray = yourInsideArray[i]
//do some
switch yourObjectInsideThisArray {
case let .integer(intValue):
print(intValue)
break
case let .string(stringValue):
print(stringValue)
break
}
}