์ง๋ ํธ์ ์ด์ด์ ์งํ!
์ด์ ์ง์ง ๋ง์ง๋ง ํํธ๋ค.
์ด์ ํธ์์๋ JSON๋ฐ์ดํฐ์ ํด๋น ํค๊ฐ ์์ด๋ ์๋ฌ๊ฐ ๋์ง ์๊ณ ๊ธฐ๋ณธ๊ฐ์ ์ง์ ํ ์ ์๊ฒ ํ๋ค.
์ด๋, Generic์ ์ด์ฉํ์์๋ค.
์ด๋ฒ ํธ์ ์์ฃผ ๊ฐ๋จํ๊ฒ ๋๋ผ ๊ฒ์ด๋ค.
๋ค๋ฅธ ํ์ ์ผ๋ก ํ๋ณํ ํ๋ ๊ฒ๊ณผ ๋ฆฌ์คํธ์ ๋ํ ์ฒ๋ฆฌ๋ค.
๋ค๋ฅธ ํ์ ์ผ๋ก ๋ฐ๊พธ๋๊ฑด ์ต์ ๋์ธ ํ์ ๊ณผ ์ต์ ๋์ด ์๋ ํ์ ์ ์ ์ฉํ ๊ฒ์ด๋ค.
์ต์ ๋์ด ์๋ ํ์
์ต์ ๋์ด ์๋๊ณ ๋ค๋ฅธ ํ์ ์บ์คํ ์ ๋ณด์
์ด์ ์ ํ๋
{
"isHidden" : "Y"
}
์ด ๊ฐ์ Bool ํํ๋ก ๋ฐ๊ธฐ๋ฅผ ์งํ ํ ๊ฑด๋ฐ,
์ด๊ฒ๋ ๊ธฐ๋ณธ๊ฐ์ด true ๋๋ false์ด๋ฏ๋ก
๋ค์ ๊ฒ๋ค๋ 2๊ฐ๊ฐ ๋์ฌ ๊ฒ์ด๋ค.
init(from decoder: Decoder){}extension KeyedDecodingContainer{}
๊ทธ๋ฌ๋ฏ๋ก ๊ทธ๋ฅ protocol๋ก ๋ฌถ์ด์ฃผ๊ณ
protocol JSONStringConverterAvailable {
static var defaultValue: Bool { get }
}
์ด์ ์ ๋ง๋ JSONDefaultWrapper์์ Property Wrapper ๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ
enum JSONDefaultWrapper {
// ...
// Property Wrapper - Optional String To Bool
@propertyWrapper
struct StringConverterWrapper<T: JSONStringConverterAvailable> {
var wrappedValue: Bool = T.defaultValue
}
// ...
}
Decodable๋ ์ ์ฉํด์ฃผ๊ณ
extension JSONDefaultWrapper.StringConverterWrapper: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.wrappedValue = (try container.decode(String.self)) == "Y"
}
}
KeyedDecodingContainer ํ์ฅ๋ ํด์ฃผ๊ณ
extension KeyedDecodingContainer {
// ...
func decode<T: JSONStringConverterAvailable>(_ type: JSONDefaultWrapper.StringConverterWrapper<T>.Type, forKey key: Key) throws -> JSONDefaultWrapper.StringConverterWrapper<T> {
try decodeIfPresent(type, forKey: key) ?? .init()
}
}
์ด์ ํธ๋ค์ ๋ดค๋ค๋ฉด ์ดํดํ๊ธฐ ํจ์ฌ ์์ํ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๊ธฐ ์ํด ์ด์ ํธ์ JSONDefaultWrapper.TypeCase์๋ ์ ์๋ฅผ ํด์ค๋ค.
๊ธฐ๋ณธ๊ฐ true, false ๋๋ค!
enum TypeCase {
enum StringFalse: JSONStringConverterAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { false }
}
enum StringTrue: JSONStringConverterAvailable {
// ๊ธฐ๋ณธ๊ฐ - false
static var defaultValue: Bool { true }
}
}
๊ทธ๋ฆฌ๊ณ ๋ง๋ฌด๋ฆฌ๋ก typealias๋ฅผ ํตํด ๊ฐ์ถ๋ ค์ค๋ค.
enum JSONDefaultWrapper {
//...
typealias StringFalse = StringConverterWrapper<JSONDefaultWrapper.TypeCase.StringFalse>
typealias StringTrue = StringConverterWrapper<JSONDefaultWrapper.TypeCase.StringTrue>
}
๊ทธ๋ผ ์ธ ์ค๋น๋ ๋๋ฌ๋ค.
๊ทธ๋ฅ property wrapper 2๊ฐ ๋ง๋๋๊ฒ ๋์๋ ค๋?
์ฐ๋ ๋ฐฉ๋ฒ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด์ ๊ณผ ๊ฐ๋ค.
class Posting: Decodable {
@JSONDefaultWrapper.StringFalse var stringFalseValue: Bool
@JSONDefaultWrapper.StringTrue var stringTrueValue: Bool
}
์ด๋ ๊ฒ ํด์ฃผ๋ฉด ์์ฃผ ์ ๋๋ค.
์ต์ ๋ ํ์
์ด๋ฒ์๋ ์กฐ๊ธ ๋ค๋ฅธ๊ฑธ ํด๋ณด์,
nil๋ก ๋
๋๋๊ฒ ๋์ ์ผ์ด์ค๊ฐ ์์ ์ ์๋ค.
์๋ฅผ ๋ค์ด timestamp๋ฅผ Date๋ก ๋ฐ๊พผ๋ค๊ฑฐ๋..?
์ด ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ ๊ฐ์ผ๋ก ์ค๋ ๋ ์ง๋ฅผ ๋ฃ๋๋ค๊ฑฐ๋ ์ด๋ฐ๊ฑด ๋ณ๋ก๋ค
์ฐจ๋ผ๋ฆฌ nil๋ก์จ ๋
๋๋๊ฒ ๋ซ๋ค๊ณ ๋ณธ๋ค.
๊ทธ๋์ ์ ์ฉ์ ํด๋ณด์.
๋ ๋จ์ ์ธ ์ผ์ด์ค๋
protocol์ ์ ์ฉํ์ง ์๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก enum JSONDefaultWrapper {} ์์ ์ ์ธ์ ํด์ค๋ค.
enum `JSONDefaultWrapper` {
// Property Wrapper - Optional Timestamp to Optinoal Date
@propertyWrapper
struct TimestampToOptionalDate {
var wrappedValue: Date?
}
}
์ฌ๊ธฐ์ ๋ด์ผํ ์ ์ wrappedValue๊ฐ ์ต์ ๋์ด๋ผ๋ ์ ?
๊ทธ๋ ๋ด ์ด๊ธฐํํด๋ ๋ฌธ์ ๊ฐ ์๋ค.
์ด์ฐจํผ nil๋ก ๋ค์ด๊ฐ๋ฉด ๋๋๊น.
(์ฌ๊ธฐ์ struct ์์ฑ๊ณผ ๋์์ Decodable์ ๋ฃ๊ณ init(from decoder: Decoder)์ ๋ง๋ค๋ฉด ์๋์ผ๋ก init()์ ์์ฑ ๋์ง ์๋ ๊ฒ์ ์๊ฒ ๋์๋ค.)
๊ทธ ๋ค์์ ๋ง์ฐฌ๊ฐ์ง๋ก
Decoadable ๋ฐ์์ฃผ๊ณ
extension JSONDefaultWrapper.TimestampToOptionalDate: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let timestamp = try container.decode(Double.self)
let date = Date.init(timeIntervalSince1970: timestamp)
self.wrappedValue = date
}
}
KeyedDecodingContainer ํ์ฅํด์ฃผ๊ณ
func decode(_ type: JSONDefaultWrapper.TimestampToOptionalDate.Type, forKey key: Key) throws -> JSONDefaultWrapper.TimestampToOptionalDate {
try decodeIfPresent(type, forKey: key) ?? .init()
}
์ด๋ฌ๋ฉด ์ค๋น๋.
๋ฆฌ์คํธ
์ง์ง ์ง์ง ๋ง๋ฌด๋ฆฌ๋ก ๋ฆฌ์คํธ ์ฒ๋ฆฌ ๋์ง๊ณ ๋๋ด๊ธฐ
๋ณ๋๋ก ๋ฉํผ ๋ง๋ค ํ์ ์๋ค. ์ด๋ฏธ ๋ค ๊ฐ์ถฐ ์ก๋ค.
JSONDefaultWrapperAvailable.TypeCase์ ์ ์๋ง ํด์ฃผ๊ณ !
enum TypeCase {
enum List<T: Decodable & ExpressibleByArrayLiteral>: JSONDefaultWrapperAvailable {
// ๊ธฐ๋ณธ๊ฐ - []
static var defaultValue: T { [] }
}
}
typealias๋ง ์กฐ๋ ์ด๋ ต๊ฒ ์๋ด์ฃผ๋ฉด
enum JSONDefaultWrapper {
typealias EmptyList<T: Decodable & ExpressibleByArrayLiteral> = Wrapper<JSONDefaultWrapper.TypeCase.List<T>>
}
์ฌ์ฉ ์ค๋น ๋!!
๊ฒฐ๊ณผ
ํค ๋ฏธ์กด์ฌ

ํค ์กด์ฌ

์์ฃผ ์ข์ใ ใ ใ ๋๋์ด ๋!