通过 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
}