Skip to content

Instantly share code, notes, and snippets.

@rizumita
Created January 18, 2018 11:35
Show Gist options
  • Save rizumita/d51a6e4c2f1232111a2339c206cfaaa0 to your computer and use it in GitHub Desktop.
Save rizumita/d51a6e4c2f1232111a2339c206cfaaa0 to your computer and use it in GitHub Desktop.
Decode [String:Any] property by Decodable in Swift
struct AnyCodingKeys: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) { self.stringValue = stringValue }
init?(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
extension KeyedDecodingContainer {
func decode(_ type: [Any].Type, forKey key: K) throws -> [Any] {
var container = try self.nestedUnkeyedContainer(forKey: key)
return try container.decode(type)
}
func decodeIfPresent(_ type: [Any].Type, forKey key: K) throws -> [Any]? {
guard contains(key) else { return .none }
return try decode(type, forKey: key)
}
func decode(_ type: [String:Any].Type, forKey key: K) throws -> [String:Any] {
let container = try nestedContainer(keyedBy: AnyCodingKeys.self, forKey: key)
return try container.decode(type)
}
func decodeIfPresent(_ type: [String:Any].Type, forKey key: K) throws -> [String:Any]? {
guard contains(key) else { return .none }
return try decode(type, forKey: key)
}
func decode(_ type: [String:Any].Type) throws -> [String:Any] {
var dictionary = [String:Any]()
allKeys.forEach { key in
if let value = try? decode(Bool.self, forKey: key) {
dictionary[key.stringValue] = value
} else if let value = try? decode(String.self, forKey: key) {
dictionary[key.stringValue] = value
} else if let value = try? decode(Int64.self, forKey: key) {
dictionary[key.stringValue] = value
} else if let value = try? decode(Double.self, forKey: key) {
dictionary[key.stringValue] = value
} else if let value = try? decode([String:Any].self, forKey: key) {
dictionary[key.stringValue] = value
} else if let value = try? decode([Any].self, forKey: key) {
dictionary[key.stringValue] = value
}
}
return dictionary
}
}
extension UnkeyedDecodingContainer {
mutating func decode(_ type: [Any].Type) throws -> [Any] {
var array = [Any]()
while isAtEnd == false {
if let value = try? decode(Bool.self) {
array.append(value)
} else if let value = try? decode(String.self) {
array.append(value)
} else if let value = try? decode(Int64.self) {
array.append(value)
} else if let value = try? decode(Double.self) {
array.append(value)
} else if let value = try? decode([String:Any].self) {
array.append(value)
} else if let value = try? decode([Any].self) {
array.append(value)
}
}
return array
}
mutating func decode(_ type: [String:Any].Type) throws -> [String:Any] {
let nestedContainer = try self.nestedContainer(keyedBy: AnyCodingKeys.self)
return try nestedContainer.decode(type)
}
}
struct A: Decodable {
let title: String
let payload: Payload
struct Payload: Decodable {
let items: [String:Any]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: AnyCodingKeys.self)
items = try container.decode([String:Any].self)
}
}
}
let jsonString = """
{
"title":"abc",
"payload": {
"int": 1,
"string": "2",
"array": {
"bool": true,
"double": 2.34
}
}
}
"""
let jsonData = jsonString.data(using: .utf8)!
let a = try! JSONDecoder().decode(A.self, from: jsonData)
print(a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment