Swift 动态 json 读写值

Swift Dynamic json Values Reading and Writing

问题卡在

我正在尝试能够将我的 json 文件数据读出到控制台日志以进行测试,以便我以后可以使用它。

由于不同的数据大小和可能的错误 json 格式,我不确定如何完成我的其他结构。

完成后,我相信我需要使用 for 循环从“M”、“S”和“WP”读取不同大小的数据(我认为这部分不应该很复杂)

可能需要考虑的事项

我要写入和添加数据到“M”“S”“WP”

("M", "S") 的数据量可以是任意数量的字符串数组数据对象

“WP”中的数据可能需要不同的格式我想添加一个名称(“abc”)和一个包含任意数量数据点的 Int 数组

注意:我的Json格式在MP和WP的某些地方可能是错误的

Swift 抓取数据的代码

import Foundation


struct UserDay: Codable {
    let mp: UserMP
    let wp: UserWP
}

struct UserMP: Codable {
    let m: [UserM]
    let s: [UserS]
}

struct UserM : Codable {
    let title: String
    let description: String
    let time: String
}
struct UserS : Codable {
    let title: String
    let description: String
    let time: String
}


struct UserWP: Codable {
    let wp: [WPData]
}

struct WPData: Codable {
    let title: String
    let values: [Int]
}


class LogDataHandler {
    
    
    public func grabJSONInfo(){
        guard let jsonURL = Bundle(for: type(of: self)).path(forResource: "LogData", ofType: "json") else { return }
        
        guard let jsonString = try? String(contentsOf: URL(fileURLWithPath: jsonURL), encoding: String.Encoding.utf8) else { return }
        
        // Print Info for TESTING
        var year: UserDay?
        
        do {
            year = try JSONDecoder().decode(UserDay.self, from: Data(jsonString.utf8))
        } catch {
            print("ERROR WHEN DECODING JSON")
        }
        
        guard let results = year else {
            print("YEAR IS NIL")
            return
        }
        
        print(results)
        
    }
    
    
}

JSON 下面的示例数据

{
    "01/01/2020": {
   
        "MP" : {
            "M" : [
                {"title" : "m1", "description" : "1", "time" : "12:30pm"},
                {"title" : "m2", "description" : "2", "time" : "1:30pm"},
                {"title" : "m3", "description" : "3", "time" : "2:30pm"}
            ],
            "S" : [
                {"title" : "s1", "description" : "1", "time" : "1pm"}
            ]
        },
        "WP" : [
            { "title" : "abc", "values" :  [12, 10, 6]},
            { "title" : "def", "values" :  [8]}
        ]
    },
    "01/29/2020": {
        
        "MP" : {
            "M" : [{"title" : "m1", "description" : "1", "time" : "12:30pm"}],
            "S" : [{"title" : "s1", "description" : "1", "time" : "12:30pm"}]
        },
        "WP" :[{ "title" : "def", "values" :  [8]}]
    }
    
}

根据评论和我们的聊天,这似乎是构建 Swift 模型和 JSON 对象的正确方法的问题。

根据您的(更新的)JSON,您可能希望将数据解码为 [String: UserDay] - 一个以日期字符串为键、以 UserDay 为值的字典。

First, WP 属性 在你的 JSON 中只是一个对象数组(映射到 WPData) , 所以最好将 UserDay.wp 改为 [WPData] 而不是 UserWP:

struct UserDay: Codable {
    let mp: UserMP
    let wp: [WPData] // <-- changed
}

其次,您的某些模型属性与 JSON 中的内容不直接匹配,因为键-属性映射区分大小写。您可以显式定义 CodingKeys 来映射它们:

struct UserDay: Codable {
    let mp: UserMP
    let wp: [WPData]

    enum CodingKeys: String, CodingKey {
        case mp = "MP", wp = "WP"
    }
}

struct UserMP: Codable {
    let m: [UserM]
    let s: [UserS]

    enum CodingKeys: String, CodingKey {
        case m = "M", s = "S"
    }
}

现在您已准备好解码 [String: UserDay]:

let userDays = try JSONDecoder().decoder([String: UserDay].self, from: jsonData)

let userDay = userDays["01/29/2020"]


当然,使用 String 而不是 Date 不是很方便。不幸的是,DictionaryCodable 的一致性仅支持 IntString 作为键(AFAIK)。

所以,让我们手动解码成一个新的根对象 UserData,它适用于 Dates:

struct UserData: Codable {
   var userDays: [Date: UserDay]

   init(from decoder: Decoder) throws {
       let container = try decoder.singleValueContainer()
       let dict = try container.decode([String: UserDay].self)

       let dateFormatter = DateFormatter()
       dateFormatter.dateFormat = "MM/dd/yyyy"
       dateFormatter.locale = Locale(identifier: "en_US_POSIX")

       // decode (String, UserDay) pairs into an array of (Date, UserDay)
       let pairs = dict.compactMap { (key, value) -> (Date, UserDay)? in
           guard let date = dateFormatter.date(from: key) else { return nil }
           return (date, value)
       }

       // uniquing is used just in case there non unique keys
       self.userDays = Dictionary(pairs, uniquingKeysWith: {(first, _) in first})
   }
}

现在,我们可以解码成这个 UserData 对象:

let userData = try JSONDecoder().decode(UserData.self, from: jsonData)

let todaysData = userData.userDays[Date()]