Với một số cảm hứng từ ý chính mà tôi tìm thấy, tôi đã viết một số tiện ích mở rộng cho UnkeyedDecodingContainer
và KeyedDecodingContainer
. Bạn có thể tìm thấy một liên kết đến ý chính của tôi ở đây . Bằng cách sử dụng mã này, bây giờ bạn có thể giải mã bất kỳ Array<Any>
hoặc Dictionary<String, Any>
bằng cú pháp quen thuộc:
let dictionary: [String: Any] = try container.decode([String: Any].self, forKey: key)
hoặc là
let array: [Any] = try container.decode([Any].self, forKey: key)
Chỉnh sửa: có một cảnh báo tôi đã tìm thấy đó là giải mã một mảng từ điển [[String: Any]]
Cú pháp bắt buộc như sau. Bạn có thể muốn tạo ra một lỗi thay vì ép buộc truyền:
let items: [[String: Any]] = try container.decode(Array<Any>.self, forKey: .items) as! [[String: Any]]
CHỈNH SỬA 2: Nếu bạn chỉ muốn chuyển đổi toàn bộ tệp sang từ điển, tốt hơn hết bạn nên sử dụng api từ JSONSerialization vì tôi chưa tìm ra cách mở rộng chính JSONDecoder để giải mã trực tiếp từ điển.
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
// appropriate error handling
return
}
Các phần mở rộng
// Inspired by https://gist.github.com/mbuchetics/c9bc6c22033014aa0c550d3b4324411a
struct JSONCodingKeys: CodingKey {
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
self.init(stringValue: "\(intValue)")
self.intValue = intValue
}
}
extension KeyedDecodingContainer {
func decode(_ type: Dictionary<String, Any>.Type, forKey key: K) throws -> Dictionary<String, Any> {
let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key)
return try container.decode(type)
}
func decodeIfPresent(_ type: Dictionary<String, Any>.Type, forKey key: K) throws -> Dictionary<String, Any>? {
guard contains(key) else {
return nil
}
guard try decodeNil(forKey: key) == false else {
return nil
}
return try decode(type, forKey: key)
}
func decode(_ type: Array<Any>.Type, forKey key: K) throws -> Array<Any> {
var container = try self.nestedUnkeyedContainer(forKey: key)
return try container.decode(type)
}
func decodeIfPresent(_ type: Array<Any>.Type, forKey key: K) throws -> Array<Any>? {
guard contains(key) else {
return nil
}
guard try decodeNil(forKey: key) == false else {
return nil
}
return try decode(type, forKey: key)
}
func decode(_ type: Dictionary<String, Any>.Type) throws -> Dictionary<String, Any> {
var dictionary = Dictionary<String, Any>()
for key in allKeys {
if let boolValue = try? decode(Bool.self, forKey: key) {
dictionary[key.stringValue] = boolValue
} else if let stringValue = try? decode(String.self, forKey: key) {
dictionary[key.stringValue] = stringValue
} else if let intValue = try? decode(Int.self, forKey: key) {
dictionary[key.stringValue] = intValue
} else if let doubleValue = try? decode(Double.self, forKey: key) {
dictionary[key.stringValue] = doubleValue
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self, forKey: key) {
dictionary[key.stringValue] = nestedDictionary
} else if let nestedArray = try? decode(Array<Any>.self, forKey: key) {
dictionary[key.stringValue] = nestedArray
}
}
return dictionary
}
}
extension UnkeyedDecodingContainer {
mutating func decode(_ type: Array<Any>.Type) throws -> Array<Any> {
var array: [Any] = []
while isAtEnd == false {
// See if the current value in the JSON array is `null` first and prevent infite recursion with nested arrays.
if try decodeNil() {
continue
} else if let value = try? decode(Bool.self) {
array.append(value)
} else if let value = try? decode(Double.self) {
array.append(value)
} else if let value = try? decode(String.self) {
array.append(value)
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self) {
array.append(nestedDictionary)
} else if let nestedArray = try? decode(Array<Any>.self) {
array.append(nestedArray)
}
}
return array
}
mutating func decode(_ type: Dictionary<String, Any>.Type) throws -> Dictionary<String, Any> {
let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self)
return try nestedContainer.decode(type)
}
}