Last active
October 3, 2018 18:30
-
-
Save takasek/ffa9c35a7c1f0baf0f9ee037937fcc24 to your computer and use it in GitHub Desktop.
Decoder, DecodingContainerの、デコード先の型を推論させたい!明示的に指定したくない! ref: http://qiita.com/takasek/items/f51c26a8ee6a2929bb6e
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
import Foundation | |
extension JSONDecoder { | |
func decode<T: Decodable>(from data: Data) throws -> T { | |
return try decode(T.self, from: data) | |
} | |
} | |
extension PropertyListDecoder { | |
func decode<T: Decodable>(from data: Data) throws -> T { | |
return try decode(T.self, from: data) | |
} | |
} | |
extension KeyedDecodingContainerProtocol { | |
func decode(forKey key: Self.Key) throws -> Bool { return try decode(Bool.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Int { return try decode(Int.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Int8 { return try decode(Int8.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Int16 { return try decode(Int16.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Int32 { return try decode(Int32.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Int64 { return try decode(Int64.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> UInt { return try decode(UInt.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> UInt8 { return try decode(UInt8.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> UInt16 { return try decode(UInt16.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> UInt32 { return try decode(UInt32.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> UInt64 { return try decode(UInt64.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Float { return try decode(Float.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> Double { return try decode(Double.self, forKey: key) } | |
func decode(forKey key: Self.Key) throws -> String { return try decode(String.self, forKey: key) } | |
func decode<T: Decodable>(forKey key: Self.Key) throws -> T { return try decode(T.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Bool? { return try decodeIfPresent(Bool.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Int? { return try decodeIfPresent(Int.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Int8? { return try decodeIfPresent(Int8.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Int16? { return try decodeIfPresent(Int16.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Int32? { return try decodeIfPresent(Int32.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Int64? { return try decodeIfPresent(Int64.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> UInt? { return try decodeIfPresent(UInt.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> UInt8? { return try decodeIfPresent(UInt8.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> UInt16? { return try decodeIfPresent(UInt16.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> UInt32? { return try decodeIfPresent(UInt32.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> UInt64? { return try decodeIfPresent(UInt64.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Float? { return try decodeIfPresent(Float.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> Double? { return try decodeIfPresent(Double.self, forKey: key) } | |
func decodeIfPresent(forKey key: Self.Key) throws -> String? { return try decodeIfPresent(String.self, forKey: key) } | |
func decodeIfPresent<T: Decodable>(forKey key: Self.Key) throws -> T? { return try decodeIfPresent(T.self, forKey: key) } | |
} | |
extension UnkeyedDecodingContainer { | |
mutating func decode() throws -> Bool { return try decode(Bool.self) } | |
mutating func decode() throws -> Int { return try decode(Int.self) } | |
mutating func decode() throws -> Int8 { return try decode(Int8.self) } | |
mutating func decode() throws -> Int16 { return try decode(Int16.self) } | |
mutating func decode() throws -> Int32 { return try decode(Int32.self) } | |
mutating func decode() throws -> Int64 { return try decode(Int64.self) } | |
mutating func decode() throws -> UInt { return try decode(UInt.self) } | |
mutating func decode() throws -> UInt8 { return try decode(UInt8.self) } | |
mutating func decode() throws -> UInt16 { return try decode(UInt16.self) } | |
mutating func decode() throws -> UInt32 { return try decode(UInt32.self) } | |
mutating func decode() throws -> UInt64 { return try decode(UInt64.self) } | |
mutating func decode() throws -> Float { return try decode(Float.self) } | |
mutating func decode() throws -> Double { return try decode(Double.self) } | |
mutating func decode() throws -> String { return try decode(String.self) } | |
mutating func decode<T: Decodable>() throws -> T { return try decode(T.self) } | |
mutating func decodeIfPresent() throws -> Bool? { return try decodeIfPresent(Bool.self) } | |
mutating func decodeIfPresent() throws -> Int? { return try decodeIfPresent(Int.self) } | |
mutating func decodeIfPresent() throws -> Int8? { return try decodeIfPresent(Int8.self) } | |
mutating func decodeIfPresent() throws -> Int16? { return try decodeIfPresent(Int16.self) } | |
mutating func decodeIfPresent() throws -> Int32? { return try decodeIfPresent(Int32.self) } | |
mutating func decodeIfPresent() throws -> Int64? { return try decodeIfPresent(Int64.self) } | |
mutating func decodeIfPresent() throws -> UInt? { return try decodeIfPresent(UInt.self) } | |
mutating func decodeIfPresent() throws -> UInt8? { return try decodeIfPresent(UInt8.self) } | |
mutating func decodeIfPresent() throws -> UInt16? { return try decodeIfPresent(UInt16.self) } | |
mutating func decodeIfPresent() throws -> UInt32? { return try decodeIfPresent(UInt32.self) } | |
mutating func decodeIfPresent() throws -> UInt64? { return try decodeIfPresent(UInt64.self) } | |
mutating func decodeIfPresent() throws -> Float? { return try decodeIfPresent(Float.self) } | |
mutating func decodeIfPresent() throws -> Double? { return try decodeIfPresent(Double.self) } | |
mutating func decodeIfPresent() throws -> String? { return try decodeIfPresent(String.self) } | |
mutating func decodeIfPresent<T: Decodable>() throws -> T? { return try decodeIfPresent(T.self) } | |
} | |
extension SingleValueDecodingContainer { | |
func decode() throws -> Bool { return try decode(Bool.self) } | |
func decode() throws -> Int { return try decode(Int.self) } | |
func decode() throws -> Int8 { return try decode(Int8.self) } | |
func decode() throws -> Int16 { return try decode(Int16.self) } | |
func decode() throws -> Int32 { return try decode(Int32.self) } | |
func decode() throws -> Int64 { return try decode(Int64.self) } | |
func decode() throws -> UInt { return try decode(UInt.self) } | |
func decode() throws -> UInt8 { return try decode(UInt8.self) } | |
func decode() throws -> UInt16 { return try decode(UInt16.self) } | |
func decode() throws -> UInt32 { return try decode(UInt32.self) } | |
func decode() throws -> UInt64 { return try decode(UInt64.self) } | |
func decode() throws -> Float { return try decode(Float.self) } | |
func decode() throws -> Double { return try decode(Double.self) } | |
func decode() throws -> String { return try decode(String.self) } | |
func decode<T: Decodable>() throws -> T { return try decode(T.self) } | |
} |
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
struct Hoge: Decodable { | |
let id: Int | |
let text: String | |
let url: URL | |
let option: String? | |
private enum CodingKeys: CodingKey { | |
case id | |
case text | |
case url | |
case option | |
} | |
init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
// 普通は型を指定しなければいけないけど、 | |
// id = try container.decode(Int.self, forKey: .id) | |
// text = try container.decode(String.self, forKey: .text) | |
// url = try container.decode(URL.self, forKey: .url) | |
// option = try container.decodeIfPresent(String.self, forKey: .option) | |
// 理屈としては、型を省略しても推論可能なので、extensionを通して実現 | |
id = try container.decode(forKey: .id) | |
text = try container.decode(forKey: .text) | |
url = try container.decode(forKey: .url) | |
option = try container.decodeIfPresent(forKey: .option) | |
} | |
} | |
let data = """ | |
{ | |
"id": 100, | |
"text": "text", | |
"url": "https://www.yahoo.co.jp", | |
"option": null, | |
} | |
""".data(using: .utf8)! | |
let decoder = JSONDecoder() | |
//let h: Hoge = try! decoder.decode(Hoge.self, from: data) // 普通は引数として型を指定しなきゃいけないけど、 | |
let h: Hoge = try! decoder.decode(from: data) // 理屈としては型を省略しても推論可能なので、extensionを通して実現 | |
print(h) | |
// Hoge(id: 100, text: "text", url: https://www.yahoo.co.jp, option: nil) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I can't get the difference between what you have here and the following extension from this post: