我使用动态字符串键解码JSON,如下所示:
{
"dynamickey1":
{"infos1": "blabla","infos2": 21},
"dynamickey2":
{"infos1": "blabla","infos2": 12},
... }
它们按我的意愿排序,因为我在URL中放了一个字符串列表。但是当它使用(编辑:我把完整的代码)下面的代码解码字典时,我丢失了订单:
struct Devise {
let nom : String
let EUR: Float
let ETH: Float
}
struct DataPrix {
let devises: [Devise]
struct DataPrixCodingKeys: CodingKey {
let stringValue : String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue : Int? {return nil}
init?(intValue: Int) {return nil}
}
enum DeviseCodingKeys: String, CodingKey {
case ETH
case EUR
}
}
let decoder = JSONDecoder()
extension DataPrix: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy : DataPrixCodingKeys.self)
self.devises = try (container.allKeys).map { key in
let devisesContainer = try container.nestedContainer(keyedBy: DeviseCodingKeys.self, forKey: key)
let deviseName = key.stringValue
let EUR = try devisesContainer.decode(Float.self, forKey: .EUR)
let ETH = try devisesContainer.decode(Float.self, forKey: .ETH)
return Devise(nom: deviseName, EUR: EUR, ETH: ETH)
}
}
}
那么可以按字母顺序对它们进行排序,或者至少保持我在初始列表中的顺序吗?
答案 0 :(得分:2)
这更可能是container
类型的问题。您似乎正在使用NSDictionary
,其allKeys
类型为Any
。 Any
不是Comparable
。
最简单的解决方案是将字典转换为[String: Any]
。然后,您可以直接使用container.keys.sorted()
,其中<
是默认比较器。
let jsonString = """
{
"dynamickey1": {"infos1": "blabla","infos2": 21},
"dynamickey2": {"infos1": "blabla","infos2": 12}
}
"""
let jsonData = jsonString.data(using: .utf8)!
if let container = (try? JSONSerialization.jsonObject(with: jsonData, options: [])) as? [String: Any] {
let sortedKeys = container.keys.sorted()
print(sortedKeys)
}
或者,切换到使用Codable
协议并安全地解码JSON类型:
let jsonString = """
{
"dynamickey1": {"infos1": "blabla","infos2": 21},
"dynamickey2": {"infos1": "blabla","infos2": 12}
}
"""
let jsonData = jsonString.data(using: .utf8)!
struct Info: Codable {
let infos1: String
let infos2: Int
}
let parsed = try? JSONDecoder().decode([String: Info].self, from: jsonData)
if let container = parsed {
print(container.keys.sorted())
}
编辑更新问题的解决方案:
let jsonString = """
{"XPR": {"EUR":0.6866,"ETH":0.001088}}
"""
let jsonData = jsonString.data(using: .utf8)!
enum Currency: String, CodingKey, Comparable {
case XPR
case EUR
case ETH
public static func < (lhs: Currency, rhs: Currency) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}
struct Devise: Decodable {
let name: String
let rates: [Currency: Double]
public init(from decoder: Decoder) throws {
name = decoder.codingPath.last?.stringValue ?? ""
let container = try decoder.container(keyedBy: Currency.self)
var rates: [Currency: Double] = [:]
try container.allKeys.forEach {
rates[$0] = try container.decode(Double.self, forKey: $0)
}
self.rates = rates
}
}
struct DataPrix: Decodable {
let devises: [Devise]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Currency.self)
devises = try container.allKeys.sorted().map {
return try container.decode(Devise.self, forKey: $0)
}
}
}
let decoder = JSONDecoder()
do {
let exchangeRates = try decoder.decode(DataPrix.self, from: jsonData)
print(exchangeRates)
} catch {
print(error)
}
但是,如果您的密钥真的是动态,那么您无法避免使用字典,最好只使用它:
let decoder = JSONDecoder()
do {
let exchangeRates = try decoder.decode([String: [String: Double]].self, from: jsonData)
print(exchangeRates)
} catch {
print(error)
}
答案 1 :(得分:1)
您可以这样排序:
let dictionary = ["key1":"test","key0":"","key5":""]
dictionary.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending }.map { key in
// code
}
因此,对于您的代码,您可以使用像这样
let keys = dic.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending }
print( keys.map { (key) -> [String : Devise]? in
guard let value = dic[key] else {return nil}
return [key : value]
}.compactMap({$0}))