Это скорее проблема с типом 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)
}