我有以下字典:
let myDict: [String: Any] = [
"first": [
"message": "qqq",
"extras": ["task": "first"]
],
"second": [
"message": "www",
"extras": ["task": "second"]
],
"third": [
"message": "eee",
"extras": ["task": "third"]
],
]
结构是可预测的:顶部关键字(first
、second
、third
)可以有任何名称,但它们总是包含一个message
字符串和一个extras
字典,后者又包含一个值为原始顶部关键字的task
。该结构是固定的,因为它会影响系统的其他部分。
现在myDict
是[String: Any]
,但这似乎可以改进,因为所有类型都是已知的。然而,我正在努力想出一个解决方案,以至于我怀疑struct
是否是一条路?
字典中的关键字数量各不相同,所以也许每个关键字都应该是struct
,而不是整个字典?我不确定。
数据将被键引用,它们的内容将被包括在生成JSON的其他键中。虽然这部分正在工作,但我不需要帮助来创建JSON。
如果字典内容的结构是固定的,那么您只需要跟踪顶部字典中每个元素的两个值。因此该结构可以定义为
struct Message {
let message: String
let key: String
}
如果你需要将其转换为字典,那么你可以添加一个计算属性:
var dictionaryRepresentation: [String: Any] {
[key: ["message": message, "extras": ["task": key]] as [String : Any]]
}
示例
let array = [Message(message: "qqq", key: "first"), Message(message: "www", key: "second"), Message(message: "eee", key: "third")]
print(array.map(.dictionaryRepresentation))
[["第一个";消息":"qqq"]],["第二个":["消息":"www","额外任务":["任务":"第二个"]]],["第三个":["消息":"eee","额外任务":[
要使用上面的示例数组完全重新创建问题中的字典,可以使用reduce(into:)
array.reduce(into: [:]) { $0[$1.key] = $1.dictionaryRepresentation}
深受Joakim解决方案的启发,但考虑到通过密钥查找消息的要求,我想出了这个:
struct Message {
let message: String
let key: String
}
extension Message {
var dictionaryRepresentation: [String: Any] {
["message": message, "extras": ["task": key] as [String: Any]]
}
}
struct Messages {
private var messages = [String: Message]()
mutating func add(_ message: String, withKey key: String) {
messages[key] = Message(message: message, key: key)
}
func message(for key: String) -> Message? {
messages[key]
}
}
extension Messages {
var dictionaryRepresentation: [String: Any] {
messages.mapValues(.dictionaryRepresentation)
}
}
您可以通过添加消息来构建消息字典:
var myMessages = Messages()
myMessages.add("qqq", withKey: "first")
myMessages.add("www", withKey: "second")
myMessages.add("eee", withKey: "third")
你可以查找一条消息:
if let secondMessage = myMessages.message(for: "second") {
print("second message is (secondMessage)")
print("second message as dictionary is (secondMessage.dictionaryRepresentation)")
}
第二条消息是message(消息:"www",密钥:"second")
作为字典的第二个消息是["消息":"www","额外":["任务":"第二个"]]
您可以获得所有消息的字典表示:
print(myMessages.dictionaryRepresentation)
["第二个":["消息":"www","附加":["任务":"第二个"]],";第三":["临时任务":["任务":"第三个"];消息":"eee"]"第一":["消息":"qqq","临时任务":["任务":"第一个"]]
您可以使用一个初始化程序来扩展Messages
,该初始化程序接受一个键和消息数组或一个键字典:消息字符串。
基于Joakim Danielson的答案,一种避免Any
:的替代方案
struct Message: Codable {
let key: String
let details: Details
init(key: String, message: String) {
self.key = key
self.details = Details(message: message, extras: ["task": key])
}
struct Details: Codable {
let message: String
let extras: [String: String]
}
}
let array = [Message(key: "first", message: "qqq"), Message(key: "second", message: "www"), Message(key: "third", message: "eee")]
let dict = array.reduce(into: [:]) { $0[$1.key] = $1.details }
将其转换为JSON:
import Foundation
let data = try JSONEncoder().encode(dict)
print(String(data: data, encoding: .utf8)!)