繁体   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