簡體   English   中英

如何使用與來自NewtonSoft(JSON.Net)組件的JSON匹配的Swift類從/向JSON讀取/寫入對象數組?

[英]How can I Read/Write array of objects from/to JSON using a Swift class that matches JSON from NewtonSoft (JSON.Net) component?

我正在嘗試讀取在另一個(Windows)程序中使用NewtonSoft JSON.Net解析器創建的JSON文件。 JSON是由JSON.Net組件在序列化對象數組時創建的。 樣本JSON如下所示(在此示例中,我僅顯示兩個對象):

[{"MaxLength":23,"HasSpecialChars":false,"HasUpperCase":true,"Key":"firstOne"},
{"MaxLength":0,"HasSpecialChars":false,"HasUpperCase":false,"Key":"secondOne"}]

請注意,這是json中的對象數組。

現在,我需要一些Swift代碼,該代碼將讀入JSON並在程序中更改值后將其寫出。

我嘗試過的

我找到了這個SO條目: 使用Swift讀取JSON文件但是,為了獲得對象數組,該條目使用了可編碼的單獨結構,如下所示:

struct ResponseData: Decodable {
    var thisNameShowsUpInJson: [SiteKey]
}

這迫使外部數組在json中擁有自己的name屬性。

例如,該文章中代碼的唯一工作方式是將我的JSON更改為包含名稱(SiteKey)的外部對象,如下所示:

 {"thisNameShowsUpInJson": [{"MaxLength":23,"HasSpecialChars":false,"HasUpperCase":true,"Key":"firstOne"},
   {"MaxLength":0,"HasSpecialChars":false,"HasUpperCase":false,"Key":"secondOne"}]
}

但是,對於JSON.Net將對象數組寫入文件的方式,這是不正確的。

這是我想要序列化和反序列化的簡單Swift類:

class SiteKey : Codable{
    var Key : String
    var MaxLength : Int
    var HasSpecialChars : Bool
    var HasUpperCase : Bool

    init(key : String, maxLength : Int,
         hasSpecialChars : Bool,
         hasUpperCase : Bool){
        Key = key;
        MaxLength = maxLength;
        HasSpecialChars = hasSpecialChars;
        HasUpperCase = hasUpperCase;
    } 
}

我想從命名文件中讀取數據,然后將數據反序列化為對象。 然后,我想將內存對象序列化回我的示例文件。

想象一下,您有一組可編碼的對象

var array = [SiteKey]()

那么您只需使用JSONEncoder將整個數組編碼為Data

do {
    let encoded = try JSONEncoder().encode(array)
} catch { print(error) }

要將Data解碼為對象數組,可以使用JSONDecoder

do {
    array = try JSONDecoder().decode([SiteKey].self, from: encoded)
} catch { print(error) }

我的建議:

  • 改用您的類結構,則可以刪除硬編碼的init因為您可以免費獲得一個
  • 用小寫字母命名變量,然后在編碼/解碼時使用編碼鍵對其重命名

struct SiteKey : Codable {

    var key : String
    var maxLength : Int
    var hasSpecialChars : Bool
    var hasUpperCase : Bool

    enum CodingKeys: String, CodingKey {
        case key = "Key"
        case maxLength = "MaxLength"
        case hasSpecialChars = "HasSpecialChars"
        case hasUpperCase = "HasUpperCase"
    }

}

我發現了需要在Swift中使用的代碼,該代碼使我可以讀寫JSON.Net輸出的JSON(對象數組)。

我向SiteKey對象添加了兩個方法:

func loadJson(filename fileName: String) -> [SiteKey]
func writeJson(filename fileName: String, allSiteKeys : [SiteKey])

第一個函數采用指向json文件的字符串,並返回文件中的SiteKeys數組。 第二個函數采用文件名和SiteKey對象數組,並將它們寫入文件。

這是帶有附加功能的更改后的SiteKey類。

class SiteKey : Codable{
    var Key : String
    var MaxLength : Int
    var HasSpecialChars : Bool
    var HasUpperCase : Bool

    init(key : String, maxLength : Int,
         hasSpecialChars : Bool,
         hasUpperCase : Bool){
        Key = key;
        MaxLength = maxLength;
        HasSpecialChars = hasSpecialChars;
        HasUpperCase = hasUpperCase;
    }

    func loadJson(filename fileName: String) -> [SiteKey]? {
        if let url = Bundle.main.url(forAuxiliaryExecutable: fileName) {
            do {
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                let allKeys = try decoder.decode([SiteKey].self, from: data)
                return allKeys
            } catch {
                print("error:\(error)")
            }
        }
        return nil
    }

    func writeJson(filename fileName: String, allSiteKeys : [SiteKey]){
        let Data = try? JSONEncoder().encode(allSiteKeys)

            let pathAsURL = URL(fileURLWithPath: fileName)
            do {
                try Data?.write(to: pathAsURL)
            }
            catch {
                print("Failed to write JSON data: \(error.localizedDescription)")
            }
    }
}

用法如下:

let newSiteKey = siteKey.loadJson(filename: "/Users/fakeUser/Documents/Dev/all.json")

當loadJson方法返回時,newSiteKey將包含可以迭代的SiteKey類對象的數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM