我试图从我在应用程序内部快速创建的数组创建JSON文件。 我需要将“数组”编码为JSON,因为我之前创建了字典和数组,而我只是将它们组合到该数组中。 在我的代码中,我有: 我先将orderArray放入dict中,然后再将dict放入order中。 如果我打印的输出是正确的 ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我在Swift中有一个[String: Codable]
字典,我想保存到用户默认值中,但是我在努力做到这一点。
我尝试使用将其转换为Data
try! JSONSerialization.data(withJSONObject: dictionary, options: .init(rawValue: 0))
但这会导致崩溃(“ JSON写入(_SwiftValue)中的类型无效”)
我试过使用JSONEncoder
:
JSONEncoder().encode(dictionary)
但这不会编译(“无法推断通用参数T”)。
当然,我可以将所有的Codables手动转换为[String:Any],然后将其写入用户默认值,但是由于Codable的全部目的是使“解码”和“编码”变得容易,所以我不确定为什么上述两种解决方案都是不可能(尤其是第二个)?
范例 :
为了重现性,您可以在Playground中使用以下代码:
import Foundation
struct A: Codable {}
struct B: Codable {}
let dict = [ "a": A(), "b": B() ] as [String : Codable]
let data = try JSONEncoder().encode(dict)
作为一般约束, Codable
和Any
是不可编码的。 使用结构而不是字典:
struct A: Codable {
let a = 0
}
struct B: Codable {
let b = "hi"
}
struct C: Codable {
let a: A
let b: B
}
let d = C(a: A(), b: B())
let data = try JSONEncoder().encode(d)
UserDefaults有一种保存[String:Any]字典的方法:
let myDictionary: [String: Any] = ["a": "one", "b": 2]
UserDefaults.standard.set(myDictionary, forKey: "key")
let retrievedDictionary: [String: Any] = UserDefaults.standard.dictionary(forKey: "key")!
print(retrievedDictionary) // prints ["a": one, "b": 2]
但是,如果字典是要保存到UserDefaults
的对象的属性,则需要为该对象实现Codable
协议。 我知道的最简单的方法是使用JSONSerialization
将字典转换为Data
对象。 以下代码对我有用:
class MyObject: Codable {
let dictionary: [String: Any]
init(dictionary: [String: Any]) {
self.dictionary = dictionary
}
enum CodingKeys: String, CodingKey {
case dictionary
}
public required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if values.contains(.dictionary), let jsonData = try? values.decode(Data.self, forKey: .dictionary) {
dictionary = (try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any]) ?? [String: Any]()
} else {
dictionary = [String: Any]()
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if !dictionary.isEmpty, let jsonData = try? JSONSerialization.data(withJSONObject: dictionary) {
try container.encode(jsonData, forKey: .dictionary)
}
}
}
要从UserDefaults
保存和检索MyObject
,可以执行以下操作:
extension UserDefaults {
func set(_ value: MyObject, forKey defaultName: String) {
guard let data = try? PropertyListEncoder().encode(value) else { return }
set(data, forKey: defaultName)
}
func myObject(forKey defaultName: String) -> MyObject? {
guard let data = data(forKey: defaultName) else { return nil }
return try? PropertyListDecoder().decode(MyObject.self, from: data)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.