如何使用与 NewtonSoft (JSON.Net) 组件中的 JSON 匹配的 Swift 类从/向 JSON 读取/写入对象数组?
Posted
技术标签:
【中文标题】如何使用与 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? 【发布时间】:2019-01-27 21:35:28 【问题描述】:我正在尝试读取我在另一个 (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 条目:Reading in a JSON File Using Swift 但是,要获取对象数组,该条目使用可编码的单独结构,如下所示:
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;
我想从命名文件中读取数据并将数据反序列化为对象。 然后,我想将内存中的对象序列化回一个文件,就像我的示例一样。
【问题讨论】:
【参考方案1】:假设您有一个可编码对象数组
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"
【讨论】:
这是非常好的附加信息。感谢发帖。【参考方案2】:我发现了我需要在 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 类对象数组。
【讨论】:
以上是关于如何使用与 NewtonSoft (JSON.Net) 组件中的 JSON 匹配的 Swift 类从/向 JSON 读取/写入对象数组?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# 进行条件序列化 - NewtonSoft.Json
您如何“真正”使用 Newtonsoft.Json 序列化循环引用对象?