Skip to content

Commit 481ac6d

Browse files
committed
update readme
1 parent be2879d commit 481ac6d

2 files changed

Lines changed: 103 additions & 14 deletions

File tree

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import CompilerPluginSupport
55
import PackageDescription
66

77
let package = Package(
8-
name: "macro-codable-kit",
8+
name: "MacroCodableKit",
99
platforms: [
1010
.macOS(.v10_15),
1111
.iOS(.v13),

README.md

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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
110111
In 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
113120
struct 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")
132226
enum 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

Comments
 (0)