Skip to content

Instantly share code, notes, and snippets.

@rizumita
Created October 26, 2017 06:52
Show Gist options
  • Save rizumita/ae789fc056805f3843a946c76e1206f8 to your computer and use it in GitHub Desktop.
Save rizumita/ae789fc056805f3843a946c76e1206f8 to your computer and use it in GitHub Desktop.
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