Swift:如何解码JSON与字典的字典与每个键是一个递增的数值?



我是Swift的新手,我被分配了一个任务来解码这个JSON:

{
"data": {
"id": 1,
"elements": {
"E01": {
"title": "cars",
"items": ["honda", "toyota", "mercedes"],
"details": {
"id": 2,
"location": "toronto"
}
},
"E02": {
"title": "bagel types",
"items": ["plain", "grain", "toasted"],
}
}
}
}

我玩了这个,我弄清楚了如何解码这个JSON时,elements是一个数组的字典没有递增的键值。这是elements看起来像这样的:

"elements": [
{
"title": "cars",
"items": ["honda", "toyota", "mercedes"],
"details": {
"id": 2,
"location": "toronto"
}
},
{
"title": "bagel types",
"items": ["plain", "grain", "toasted"],
}
]

这是我的代码如何解码JSON时,elements看起来像JSON直接在上面:

我解码到的类:

public class StructureContainer: Codable {
let data: DataStructure

init(data: DataStructure) {
self.data = data
}
}
public class DataStructure: Codable {
let id: Int64?
let elements: [ElementStructure]?

init(id: Int64?, elements: [ElementStructure]?) {
self.id = id
self.elements = elements
}
}
public class ElementStructure: Codable {
let title: String?
let items: [String]?
let details: DetailStructure?

init(title: String?, items: [String]?, details: DetailStructure?) {
self.title = title
self.items = items
self.details = details
}
}
public class DetailStructure: Codable {
var id: Int64?
var location: String?

init(id: Int64?, location: String?) {
self.id = id
self.location = location
}
}

我是如何解码的:

func parseJSONLocally() {
do {
// JSONText is the variable that contains the JSON string
let jsonData = JSONText.data(using: .utf8)!
// dataInstance is the variable of type Structure that stores the parsed object.
dataInstance = try JSONDecoder().decode(StructureContainer.self, from: jsonData)
}
catch {
print("error", error)
}
}

当elements是一个没有递增键的字典数组时,我能够成功地解码这个。但是,当elements是每个键递增的字典的字典时,我不知道如何解码。

我在StackOverflow上发现了类似的问题,但我认为我没有看到我的确切问题。我也是Swift的新手,所以我可能会遗漏一些知识。如有任何帮助,不胜感激。

首先Int64没有意义。在所有现代计算机上,Int64等于Int。并且只声明属性为可选的,可以是nil

假设字典键不重要,实现init(from decoder解码字典版本,解码[String:ElementStructure],并将keys排序的字典values赋值给elements

public class DataStructure: Decodable {
let id: Int
let elements: [ElementStructure] // why not just Element?

private enum CodingKeys : String, CodingKey { case id, elements }

required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey:  .id)
let elementData = try container.decode([String:ElementStructure].self, forKey: .elements)
let sortedkeys = elementData.keys.sorted{ $0.localizedStandardCompare($1) == .orderedAscending }
elements = sortedkeys.map{elementData[$0]!}
}
}

最新更新