@@ -15,6 +15,7 @@ I remove the heavy swift-format dependency to reduce compile time and potential
1515 - [ Basics - @Codable ] ( #basics---codable )
1616 - [ @AllOfCodable ] ( #allofcodable )
1717 - [ @OneOfCodable ] ( #oneofcodable )
18+ - [ @TaggedCodable ] ( #taggedcodable )
1819 - [ Annotations] ( #annotations )
1920 - [ @CodingKey ] ( #codingkey )
2021 - [ @OmitCoding ] ( #omitcoding )
@@ -108,15 +109,32 @@ SocialUser:
108109` ` `
109110
110111In Swift code it could be implemented with just ` AllOfCodable` annotation
112+
111113` ` ` swift
114+ struct User: Codable {
115+ let name: String
116+ let email: String
117+ }
118+
112119@AllOfCodable
113120struct SocialUser {
114- struct Properties: Codable {
115- let isPublic: Bool
116- let username: String
117- }
118- let user: User
119- let additionalProperties: Properties
121+ struct Properties: Codable {
122+ let username: String
123+ let isPublic: Bool
124+ }
125+ let user: User
126+ let additionalProperties: Properties
127+ }
128+ ` ` `
129+
130+ `@AllOfCodable` merges all stored properties into a single flat JSON object :
131+
132+ ` ` ` json
133+ {
134+ "name": "John Doe",
135+ "email": "john@example.com",
136+ "username": "johndoe",
137+ "isPublic": true
120138}
121139` ` `
122140
@@ -128,16 +146,87 @@ struct SocialUser {
128146> Only one associated value is expected in each enum case
129147
130148` ` ` swift
149+ struct ImagePayload: Codable { let url: String; let width: Int; let height: Int }
150+ struct VideoPayload: Codable { let url: String; let duration: Int }
151+ struct FilePayload: Codable { let url: String; let name: String }
152+
131153@OneOfCodable
154+ enum MediaAttachment {
155+ case image(ImagePayload)
156+ case video(payload: VideoPayload)
157+ case file(_ payload: FilePayload)
158+ }
159+ ` ` `
160+
161+ This encodes/decodes the following JSON shapes :
162+
163+ ` ` ` json
164+ // MediaAttachment.image(ImagePayload(url: "https://example.com/photo.jpg", width: 1920, height: 1080))
165+ {"image": {"url": "https://example.com/photo.jpg", "width": 1920, "height": 1080}}
166+
167+ // MediaAttachment.video(payload: VideoPayload(url: "https://example.com/clip.mp4", duration: 30))
168+ {"video": {"url": "https://example.com/clip.mp4", "duration": 30}}
169+
170+ // MediaAttachment.file(FilePayload(url: "https://example.com/doc.pdf", name: "report.pdf"))
171+ {"file": {"url": "https://example.com/doc.pdf", "name": "report.pdf"}}
172+ ` ` `
173+
174+ # ## @TaggedCodable
175+
176+ `@TaggedCodable` generates `Codable` conformance for enums using an **adjacently tagged** format : one JSON key holds the discriminator tag, and a separate key holds the associated-value parameters.
177+
178+ Use it together with `@CodedAt` (specifies the tag key and case-name style) and `@ContentAt` (specifies the params key) :
179+
180+ ` ` ` swift
181+ @TaggedCodable
182+ @CodedAt("type", caseStyle: .screamingSnakeCase)
183+ @ContentAt("data")
184+ enum PaymentMethod {
185+ case card(number: String, expiry: String)
186+ case applePay(token: String)
187+ case sepa(iban: String)
188+ }
189+ ` ` `
190+
191+ This encodes/decodes the following JSON shapes :
192+
193+ ` ` ` json
194+ // PaymentMethod.card(number: "4242424242424242", expiry: "12/26")
195+ {"type": "CARD", "data": {"number": "4242424242424242", "expiry": "12/26"}}
196+
197+ // PaymentMethod.applePay(token: "tok_abc123")
198+ {"type": "APPLE_PAY", "data": {"token": "tok_abc123"}}
199+
200+ // PaymentMethod.sepa(iban: "DE89370400440532013000")
201+ {"type": "SEPA", "data": {"iban": "DE89370400440532013000"}}
202+ ` ` `
203+
204+ > **Note**
205+ > Cases with no associated values omit the params key entirely when encoding, and tolerate its absence when decoding.
206+
207+ # ### `caseStyle` options
208+
209+ The `caseStyle` parameter of `@CodedAt` controls how Swift case names map to the tag string in JSON :
210+
211+ | Style | Swift case | JSON tag |
212+ |---|---|---|
213+ | `.screamingSnakeCase` *(default)* | `applePay` | `"APPLE_PAY"` |
214+ | `.snakeCase` | `applePay` | `"apple_pay"` |
215+ | `.camelCase` | `applePay` | `"applePay"` |
216+ | `.verbatim` | `applePay` | `"applePay"` |
217+
218+ # ### Custom keys
219+
220+ Any string is valid for both the tag key and the params key :
221+
222+ ` ` ` swift
223+ @TaggedCodable
224+ @CodedAt("payment_type", caseStyle: .snakeCase)
225+ @ContentAt("payment_data")
132226enum PaymentMethod {
133- case card(DebitCardPayload)
134- case applePay(payload: ApplePayPayload)
135- case sepa(_ payload: SepaPayload)
227+ case applePay(token: String)
136228}
137- // valid jsons:
138- // { "card": { ... DebitCardPayload ... }
139- // { "applePay": { ... ApplePayPayload ... } }
140- // { "sepa": { ... SepaPayload ... } }
229+ // encodes as: {"payment_type": "apple_pay", "payment_data": {"token": "..."}}
141230` ` `
142231
143232# ## Annotations
0 commit comments