使用嵌套字典生成可预测的数据结构,而无需使用Any

  • 本文关键字:数据结构 Any 字典 嵌套 swift
  • 更新时间 :
  • 英文 :


我有以下字典:

let myDict: [String: Any] = [
"first": [
"message": "qqq",
"extras": ["task": "first"]
],
"second": [
"message": "www",
"extras": ["task": "second"]
],
"third": [
"message": "eee",
"extras": ["task": "third"]
],
]

结构是可预测的:顶部关键字(firstsecondthird)可以有任何名称,但它们总是包含一个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)!)

相关内容

  • 没有找到相关文章

最新更新