有人可以帮助我解码来自大量数据库的SQL查询结果吗?我还没有找到任何提示...
那里有很多示例,但是对于像这样针对流入数据库的SQL查询这样的结构,什么都无法解码...
{
"results": [
{
"statement_id": 0,
"series": [
{
"name": "XiaomiMiSensors",
"columns": [
"time",
"battery",
"collectorip",
"collectormac",
"conductivity",
"cputmp",
"firmwareversion",
"light",
"mac",
"moisture",
"sensorname",
"temperature"
],
"values": [
[
"2019-06-23T11:16:52Z",
23,
"192.168.178.81",
"B8:27:EB:0A:47:12",
1434,
66.604,
"3.1.9",
7670,
"C4:7C:8D:65:FA:95",
52,
"Plumeria",
23.6
],
[
"2019-06-23T12:19:56Z",
36,
"192.168.178.81",
"B8:27:EB:0A:47:12",
1401,
66.604,
"3.1.9",
10160,
"C4:7C:8D:65:FA:95",
53,
"Plumeria",
26.8
]
]
}
]
}
}
我尝试过这个
struct Response: Decodable {
var values: [[[IntOrString]]]
}
struct Response1: Decodable {
var columns: [IntOrString]
}
enum IntOrString: Decodable {
case int(Int)
case string(String)
init(from decoder: Decoder) throws {
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
if let int = try? decoder.singleValueContainer().decode(Int.self) {
self = .int(int)
return
}
throw IntOrStringError.intOrStringNotFound
}
enum IntOrStringError: Error {
case intOrStringNotFound
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let data = """
{
"series": [
{
"name": "XiaomiMiSensors",
"columns": [
"T1", "C2", "d3"
],
"values": [
[1, 1, 7, "Azuan Child", "Anak Azuan", "12345", "ACTIVE", "Morning", 7, 12, "2017-11-09 19:45:00"],
[28, 1, 0, "Azuan Child2", "Amran", "123456", "ACTIVE", "Evening", 1, 29, "2017-11-09 19:45:00"]
]
}
]
}
""".data(using: .utf8)!
if let response = try? JSONDecoder().decode(Response.self, from: data) {
let values = response.values
for value in values {
for intOrString in value {
switch intOrString {
case .int(let int): print("It's an int: \(int)")
case .string(let string): print("It's a string: \(string)")
}
}
}
}
if let response1 = try? JSONDecoder().decode(Response1.self, from: data) {
let columns = response1.columns
for intOrString in columns {
switch intOrString {
case .int(let int): print("It's an int: \(int)")
case .string(let string): print("It's a string: \(string)")
}
}
}
}
}
还有这个
import Foundation
struct RawServerResponse {
enum OuterKeys: String, CodingKey {
case results
}
enum RootKeys: String, CodingKey {
case id, user, reviewCount = "reviews_count"
}
enum UserKeys: String, CodingKey {
case userName = "user_name", realInfo = "real_info"
}
enum RealInfoKeys: String, CodingKey {
case fullName = "full_name"
}
enum ReviewCountKeys: String, CodingKey {
case count
}
let results: Int
let id: Int
let userName: String
let fullName: String
let reviewCount: Int
}
extension RawServerResponse: Decodable {
init(from decoder: Decoder) throws {
// results
let outerContainer = try decoder.container(keyedBy: OuterKeys.self)
// id
let container = try decoder.container(keyedBy: RootKeys.self)
id = try container.decode(Int.self, forKey: .id)
// userName
let userContainer = try container.nestedContainer(keyedBy: UserKeys.self, forKey: .user)
userName = try userContainer.decode(String.self, forKey: .userName)
// fullName
let realInfoKeysContainer = try userContainer.nestedContainer(keyedBy: RealInfoKeys.self, forKey: .realInfo)
fullName = try realInfoKeysContainer.decode(String.self, forKey: .fullName)
// reviewCount
var reviewUnkeyedContainer = try container.nestedUnkeyedContainer(forKey: .reviewCount)
var reviewCountArray = [Int]()
while !reviewUnkeyedContainer.isAtEnd {
let reviewCountContainer = try reviewUnkeyedContainer.nestedContainer(keyedBy: ReviewCountKeys.self)
reviewCountArray.append(try reviewCountContainer.decode(Int.self, forKey: .count))
}
guard let reviewCount = reviewCountArray.first else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: container.codingPath + [RootKeys.reviewCount], debugDescription: "reviews_count cannot be empty"))
}
self.reviewCount = reviewCount
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let jsonString = """
{
"results": [
{
"id": 1,
"user": {
"user_name": "Tester",
"real_info": {
"full_name":"Jon Doe"
}
},
"reviews_count": [
{
"count": 4
}
]
}
]
}
"""
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let serverResponse = try! decoder.decode(RawServerResponse.self, from: jsonData)
dump(serverResponse)
}
}
但两者显然都无法正常工作...
答案 0 :(得分:0)
尝试一下:
// MARK: - Response
struct Response: Codable {
let results: [Result]
}
// MARK: - Result
struct Result: Codable {
let statementID: Int
let series: [Series]
enum CodingKeys: String, CodingKey {
case statementID = "statement_id"
case series
}
}
// MARK: - Series
struct Series: Codable {
let name: String
let columns: [String]
let values: [[Value]]
}
enum Value: 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(Value.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Value"))
}
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)
}
}
}
do {
let response = try JSONDecoder().decode(Response.self, from: jsonData)
print(response)
} catch {
print(error)
}