Skip to content

Instantly share code, notes, and snippets.

@tadija
Last active October 26, 2021 18:31
Show Gist options
  • Save tadija/69055043ee29afe736ae979d0d6a7645 to your computer and use it in GitHub Desktop.
Save tadija/69055043ee29afe736ae979d0d6a7645 to your computer and use it in GitHub Desktop.
AEJSONSerialization
/**
* https://gist.github.com/tadija/69055043ee29afe736ae979d0d6a7645
* Revision 3
* Copyright © 2018-2021 Marko Tadić
* Licensed under the MIT license
*/
import Foundation
public extension Data {
init(withJSONObject object: Any) throws {
if JSONSerialization.isValidJSONObject(object) {
self = try JSONSerialization.data(
withJSONObject: object,
options: .prettyPrinted
)
} else {
print("IMPORTANT ⚠️ Error while creating data from JSON!")
throw JSONError.invalidObject
}
}
func toDictionary() throws -> [String: Any] {
try serializeJSON()
}
func toArray() throws -> [Any] {
try serializeJSON()
}
private func serializeJSON<T>() throws -> T {
let jsonObject = try JSONSerialization.jsonObject(
with: self, options: .allowFragments
)
guard let parsed = jsonObject as? T else {
throw JSONError.serializationFailed
}
return parsed
}
}
public extension Decodable {
init(from dictionary: [String: Any]) throws {
let data = try Data(withJSONObject: dictionary)
self = try JSONDecoder().decode(Self.self, from: data)
}
init(from array: [Any]) throws {
let data = try Data(withJSONObject: array)
self = try JSONDecoder().decode(Self.self, from: data)
}
}
public extension Encodable {
func toDictionary() throws -> [String: Any] {
try jsonData().toDictionary()
}
func toArray() throws -> [Any] {
try jsonData().toArray()
}
func jsonData() throws -> Data {
try JSONEncoder().encode(self)
}
}
public extension Dictionary where Key: ExpressibleByStringLiteral {
func codable<T: Codable>(forKey key: String) throws -> T {
guard let value = self[key as! Key] else {
throw JSONError.valueMissing(forKey: key)
}
guard let dict = value as? [String : Any] else {
throw JSONError.valueTypeWrong(forKey: key)
}
let data = try Data(withJSONObject: dict)
return try JSONDecoder().decode(T.self, from: data)
}
func codableArray<T: Codable>(forKey key: String) throws -> [T] {
guard let value = self[key as! Key] else {
throw JSONError.valueMissing(forKey: key)
}
guard let array = value as? [[String : Any]] else {
throw JSONError.valueTypeWrong(forKey: key)
}
let data = try Data(withJSONObject: array)
return try JSONDecoder().decode([T].self, from: data)
}
}
public enum JSONError: Error {
case invalidObject
case valueMissing(forKey: String)
case valueTypeWrong(forKey: String)
case serializationFailed
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment