Last active
September 11, 2020 06:27
-
-
Save thara/8a0cae6cda0f1eb69763e3ee0639f250 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// from https://stackoverflow.com/a/46049763 | |
import Foundation | |
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 { | |
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) | |
} | |
} | |
let jsonString = #"{"a": 123, "b": {"s": "x", "i": 3}}"# | |
struct Z: Decodable { | |
let a: Int | |
let b: Dictionary<String, Any> | |
init(a: Int, b: Dictionary<String, Any>) { | |
self.a = a | |
self.b = b | |
} | |
init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
self.a = try container.decode(Int.self, forKey: .a) | |
self.b = try container.decode([String: Any].self, forKey: .b) | |
} | |
enum CodingKeys: String, CodingKey { | |
case a, b | |
} | |
} | |
let z = try JSONDecoder().decode(Z.self, from: jsonString.data(using: .utf8)!) | |
print(z) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment