Created
October 26, 2017 06:52
-
-
Save rizumita/ae789fc056805f3843a946c76e1206f8 to your computer and use it in GitHub Desktop.
This file contains 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
let json = """ | |
{ | |
"id": 1, | |
"url":"", | |
"size":{ "width": 100, "height": 50 } | |
} | |
""".data(using: .utf8)! | |
protocol MyCodable: Codable { | |
static func decode(from decoder: Decoder) throws -> Self | |
func myEncode(to encoder: Encoder) throws | |
} | |
extension URL: MyCodable { | |
static func decode(from decoder: Decoder) throws -> URL { | |
let container = try decoder.singleValueContainer() | |
guard let result = URL(string: try container.decode(String.self)) else { throw NSError() } | |
return result | |
} | |
func myEncode(to encoder: Encoder) throws { | |
var container = encoder.singleValueContainer() | |
try container.encode(self) | |
} | |
} | |
extension CGSize: MyCodable { | |
static func decode(from decoder: Decoder) throws -> CGSize { | |
let container = try decoder.container(keyedBy: CGSizeCodingKeys.self) | |
let width = try container.decode(Int.self, forKey: .width) | |
let height = try container.decode(Int.self, forKey: .height) | |
return CGSize(width: width, height: height) | |
} | |
func myEncode(to encoder: Encoder) throws { | |
var container = encoder.container(keyedBy: CGSizeCodingKeys.self) | |
try container.encode(width, forKey: .width) | |
try container.encode(height, forKey: .height) | |
} | |
enum CGSizeCodingKeys: CodingKey { | |
case width | |
case height | |
} | |
} | |
extension Optional: MyCodable { | |
static func decode(from decoder: Decoder) throws -> Optional<Wrapped> { | |
if let myCodable = Wrapped.self as? MyCodable.Type { | |
return try? myCodable.decode(from: decoder) as! Wrapped | |
} else { | |
return .none | |
} | |
} | |
func myEncode(to encoder: Encoder) throws { | |
if case let .some(wrapped as MyCodable) = self { | |
try wrapped.myEncode(to: encoder) | |
} else { | |
var container = encoder.singleValueContainer() | |
try container.encodeNil() | |
} | |
} | |
} | |
struct CodableWrapper<T: MyCodable>: Codable { | |
let value: T | |
public init(from decoder: Decoder) throws { | |
value = try T.decode(from: decoder) | |
} | |
func encode(to encoder: Encoder) throws { | |
try value.myEncode(to: encoder) | |
} | |
} | |
struct Hoge: Codable { | |
let id: Int | |
let url: CodableWrapper<URL?> | |
let size: CodableWrapper<CGSize> | |
} | |
do { | |
let hoge = try JSONDecoder().decode(Hoge.self, from: json) | |
hoge.url.value | |
hoge.size.value | |
let data = try JSONEncoder().encode(hoge) | |
let object = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] | |
print(object) | |
} catch let e { | |
print(e) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment