通过 PHP 将来自 MySQL 的 JSON 解码为 SwiftUI 中的复杂结构
Decoding JSON coming from MySQL via PHP to a complex Struct in SwiftUI
我有这个JSON-文件来自MySQL-数据库通过PHP:
[
{
"id":1,
"partner":{
"id":1,
"name":"Migros Bank",
"image":"migrosbank"
},
"name":"Testkonto 1",
"type":"bank",
"iban":"CH12 1234 1234 1234 1234 1",
"datapoints":[
{
"id":1,
"depot_id":1,
"date":"2021-12-28",
"amount":5811.490234375
},
{
"id":2,
"depot_id":1,
"date":"2021-12-29",
"amount":7736.89013671875
}
]
},
{
"id":2,
"partner":{
"id":1,
"name":"Migros Bank",
"image":"migrosbank"
},
"name":"Testkonto 2",
"type":"bank",
"iban":"CH12 1234 1234 1234 1234 2",
"datapoints":[
{
"id":3,
"depot_id":2,
"date":"2021-12-28",
"amount":500
},
{
"id":4,
"depot_id":2,
"date":"2021-12-29",
"amount":1500
}
]
}
]
在 SwiftUI 中,我尝试将其解码为名为 Depot 的自定义结构,该结构由自定义结构 Partner 的一个实例和自定义结构 Depotstand 的一组实例组成:
import Foundation
import SwiftUI
struct Partner: Hashable, Codable, Identifiable {
var id: Int
var name: String
var image: String
var imageName: Image {
Image(image)
}
}
struct Depotstand: Hashable, Codable, Identifiable {
var id: Int
var depot_id: Int
var date: Date
var amount: Double
}
struct Depot: Hashable, Codable, Identifiable {
var id: Int
var partner: Partner
var name: String
var type: String
var iban: String
var datapoints: [Depotstand]
}
我添加了一个数据模型,以从我的网络服务器获取 JSON-数据 - 这部分工作正常 - 然后我尝试将数据解码到自定义结构 Depot,但失败了(它有效,如果我将 JSON/struct 简化为仅简单的 Depot 结构而不依赖于 Partner 和 Depotstand 实例):
import Foundation
final class ModelDataDepot: ObservableObject {
@Published var depots = [Depot]()
init(){
let url = URL(string: "https://api.webcoders.ch/index.php")!
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
if let data = data {
let decodedData = try JSONDecoder().decode([Depot].self, from: data)
DispatchQueue.main.async {
self.depots = decodedData
}
} else {
print("No Data!")
}
} catch {
print("JSON-Error: \(error)")
}
}.resume()
}
}
这是我得到的错误,主要包含数据类型错误,但我不知道如何解决这个问题:
JSON-Error: typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "datapoints", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "date", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil))
我已经尝试过一些不同的数据转换,甚至使用 Numberformatters 等。但我无法让它工作...我还检查了 this article 关于转换 JSON-数据进入复杂的 swift 结构,但我无法解决我的问题。
谢谢你帮我!
P.s:我是 SwiftUI 和一般移动开发的绝对初学者...我的编码背景主要是 PHP、PowerShell 等,所以请耐心等待。 :-)
你可以用 var date: Date
试试这个:
final class ModelDataDepot: ObservableObject {
@Published var depots = [Depot]()
let dataDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
init(){
let url = URL(string: "https://api.webcoders.ch/index.php")!
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
if let data = data {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(self.dataDateFormat) //<-- here
let decodedData = try decoder.decode([Depot].self, from: data)
DispatchQueue.main.async {
print("\n-----> decodedData: \(decodedData) \n")
self.depots = decodedData
}
} else {
print("No Data!")
}
} catch {
print("JSON-Error: \(error)")
}
}.resume()
}
}
struct Depotstand: Hashable, Codable, Identifiable {
var id: Int
var depot_id: Int
var date: Date
var amount: Double
}
我有这个JSON-文件来自MySQL-数据库通过PHP:
[
{
"id":1,
"partner":{
"id":1,
"name":"Migros Bank",
"image":"migrosbank"
},
"name":"Testkonto 1",
"type":"bank",
"iban":"CH12 1234 1234 1234 1234 1",
"datapoints":[
{
"id":1,
"depot_id":1,
"date":"2021-12-28",
"amount":5811.490234375
},
{
"id":2,
"depot_id":1,
"date":"2021-12-29",
"amount":7736.89013671875
}
]
},
{
"id":2,
"partner":{
"id":1,
"name":"Migros Bank",
"image":"migrosbank"
},
"name":"Testkonto 2",
"type":"bank",
"iban":"CH12 1234 1234 1234 1234 2",
"datapoints":[
{
"id":3,
"depot_id":2,
"date":"2021-12-28",
"amount":500
},
{
"id":4,
"depot_id":2,
"date":"2021-12-29",
"amount":1500
}
]
}
]
在 SwiftUI 中,我尝试将其解码为名为 Depot 的自定义结构,该结构由自定义结构 Partner 的一个实例和自定义结构 Depotstand 的一组实例组成:
import Foundation
import SwiftUI
struct Partner: Hashable, Codable, Identifiable {
var id: Int
var name: String
var image: String
var imageName: Image {
Image(image)
}
}
struct Depotstand: Hashable, Codable, Identifiable {
var id: Int
var depot_id: Int
var date: Date
var amount: Double
}
struct Depot: Hashable, Codable, Identifiable {
var id: Int
var partner: Partner
var name: String
var type: String
var iban: String
var datapoints: [Depotstand]
}
我添加了一个数据模型,以从我的网络服务器获取 JSON-数据 - 这部分工作正常 - 然后我尝试将数据解码到自定义结构 Depot,但失败了(它有效,如果我将 JSON/struct 简化为仅简单的 Depot 结构而不依赖于 Partner 和 Depotstand 实例):
import Foundation
final class ModelDataDepot: ObservableObject {
@Published var depots = [Depot]()
init(){
let url = URL(string: "https://api.webcoders.ch/index.php")!
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
if let data = data {
let decodedData = try JSONDecoder().decode([Depot].self, from: data)
DispatchQueue.main.async {
self.depots = decodedData
}
} else {
print("No Data!")
}
} catch {
print("JSON-Error: \(error)")
}
}.resume()
}
}
这是我得到的错误,主要包含数据类型错误,但我不知道如何解决这个问题:
JSON-Error: typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "datapoints", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "date", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil))
我已经尝试过一些不同的数据转换,甚至使用 Numberformatters 等。但我无法让它工作...我还检查了 this article 关于转换 JSON-数据进入复杂的 swift 结构,但我无法解决我的问题。
谢谢你帮我!
P.s:我是 SwiftUI 和一般移动开发的绝对初学者...我的编码背景主要是 PHP、PowerShell 等,所以请耐心等待。 :-)
你可以用 var date: Date
试试这个:
final class ModelDataDepot: ObservableObject {
@Published var depots = [Depot]()
let dataDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
init(){
let url = URL(string: "https://api.webcoders.ch/index.php")!
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
if let data = data {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(self.dataDateFormat) //<-- here
let decodedData = try decoder.decode([Depot].self, from: data)
DispatchQueue.main.async {
print("\n-----> decodedData: \(decodedData) \n")
self.depots = decodedData
}
} else {
print("No Data!")
}
} catch {
print("JSON-Error: \(error)")
}
}.resume()
}
}
struct Depotstand: Hashable, Codable, Identifiable {
var id: Int
var depot_id: Int
var date: Date
var amount: Double
}