Skip to content

Commit a3f95d9

Browse files
rosskimesmbrandonw
andauthored
_CodableJSONRepresentation Date Decoding (#53)
* _CodableJSONRepresentation’s jsonEncoder.dateEncodingStrategy matches the jsonDecoder.dateDecodingStrategy. * Add some tests for correct behavior. --------- Co-authored-by: Brandon Williams <[email protected]>
1 parent 3f685ce commit a3f95d9

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

Sources/StructuredQueriesCore/QueryRepresentable/Codable+JSON.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ private let jsonDecoder: JSONDecoder = {
6464

6565
private let jsonEncoder: JSONEncoder = {
6666
var encoder = JSONEncoder()
67+
encoder.dateEncodingStrategy = .custom { date, encoder in
68+
var container = encoder.singleValueContainer()
69+
try container.encode(date.iso8601String)
70+
}
6771
#if DEBUG
6872
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
6973
#endif

Tests/StructuredQueriesTests/KitchenSinkTests.swift

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ extension SnapshotTests {
4343
"julianDayDate" REAL NOT NULL DEFAULT 2456789.0,
4444
"optionalJulianDayDate" REAL,
4545
"jsonArray" TEXT NOT NULL DEFAULT '[]',
46-
"optionalJSONArray" TEXT
46+
"optionalJSONArray" TEXT,
47+
"jsonArrayOfDates" TEXT NOT NULL DEFAULT '[]'
4748
)
4849
"""
4950
)
@@ -72,7 +73,8 @@ extension SnapshotTests {
7273
iso8601Date: Date(timeIntervalSinceReferenceDate: 24 * 60 * 60),
7374
unixTimeDate: Date(timeIntervalSince1970: 24 * 60 * 60),
7475
julianDayDate: Date(timeIntervalSinceReferenceDate: 7 * 24 * 60 * 60),
75-
jsonArray: ["Hello", "world"]
76+
jsonArray: ["Hello", "world"],
77+
jsonArrayOfDates: [Date(timeIntervalSinceReferenceDate: 1234567890)]
7678
),
7779
KitchenSink(
7880
id: 3,
@@ -94,7 +96,8 @@ extension SnapshotTests {
9496
julianDayDate: Date(timeIntervalSinceReferenceDate: 7 * 24 * 60 * 60),
9597
optionalJulianDayDate: Date(timeIntervalSinceReferenceDate: 2 * 7 * 24 * 60 * 60),
9698
jsonArray: ["Hello", "world"],
97-
optionalJSONArray: ["Goodnight", "moon"]
99+
optionalJSONArray: ["Goodnight", "moon"],
100+
jsonArrayOfDates: [Date(timeIntervalSinceReferenceDate: 1234567890)]
98101
),
99102
]
100103
)
@@ -106,10 +109,10 @@ extension SnapshotTests {
106109
KitchenSink.all
107110
) {
108111
"""
109-
SELECT "kitchenSinks"."id", "kitchenSinks"."kitchenID", "kitchenSinks"."bool", "kitchenSinks"."optionalBool", "kitchenSinks"."string", "kitchenSinks"."optionalString", "kitchenSinks"."int", "kitchenSinks"."optionalInt", "kitchenSinks"."double", "kitchenSinks"."optionalDouble", "kitchenSinks"."rawRepresentable", "kitchenSinks"."optionalRawRepresentable", "kitchenSinks"."iso8601Date", "kitchenSinks"."optionalISO8601Date", "kitchenSinks"."unixTimeDate", "kitchenSinks"."optionalUnixTimeDate", "kitchenSinks"."julianDayDate", "kitchenSinks"."optionalJulianDayDate", "kitchenSinks"."jsonArray", "kitchenSinks"."optionalJSONArray"
112+
SELECT "kitchenSinks"."id", "kitchenSinks"."kitchenID", "kitchenSinks"."bool", "kitchenSinks"."optionalBool", "kitchenSinks"."string", "kitchenSinks"."optionalString", "kitchenSinks"."int", "kitchenSinks"."optionalInt", "kitchenSinks"."double", "kitchenSinks"."optionalDouble", "kitchenSinks"."rawRepresentable", "kitchenSinks"."optionalRawRepresentable", "kitchenSinks"."iso8601Date", "kitchenSinks"."optionalISO8601Date", "kitchenSinks"."unixTimeDate", "kitchenSinks"."optionalUnixTimeDate", "kitchenSinks"."julianDayDate", "kitchenSinks"."optionalJulianDayDate", "kitchenSinks"."jsonArray", "kitchenSinks"."optionalJSONArray", "kitchenSinks"."jsonArrayOfDates"
110113
FROM "kitchenSinks"
111114
"""
112-
} results: {
115+
}results: {
113116
"""
114117
┌──────────────────────────────────────────────────────────┐
115118
│ KitchenSink( │
@@ -132,7 +135,8 @@ extension SnapshotTests {
132135
│ julianDayDate: Date(2014-05-11T12:00:00.000Z), │
133136
│ optionalJulianDayDate: nil, │
134137
│ jsonArray: [], │
135-
│ optionalJSONArray: nil │
138+
│ optionalJSONArray: nil, │
139+
│ jsonArrayOfDates: [] │
136140
│ ) │
137141
├──────────────────────────────────────────────────────────┤
138142
│ KitchenSink( │
@@ -158,7 +162,10 @@ extension SnapshotTests {
158162
│ [0]: "Hello", │
159163
│ [1]: "world"
160164
│ ], │
161-
│ optionalJSONArray: nil │
165+
│ optionalJSONArray: nil, │
166+
│ jsonArrayOfDates: [ │
167+
│ [0]: Date(2040-02-14T23:31:30.000Z) │
168+
│ ] │
162169
│ ) │
163170
├──────────────────────────────────────────────────────────┤
164171
│ KitchenSink( │
@@ -187,6 +194,9 @@ extension SnapshotTests {
187194
│ optionalJSONArray: [ │
188195
│ [0]: "Goodnight", │
189196
│ [1]: "moon"
197+
│ ], │
198+
│ jsonArrayOfDates: [ │
199+
│ [0]: Date(2040-02-14T23:31:30.000Z) │
190200
│ ] │
191201
│ ) │
192202
└──────────────────────────────────────────────────────────┘
@@ -201,11 +211,11 @@ extension SnapshotTests {
201211
.select { ($0, $1.jsonGroupArray()) }
202212
) {
203213
"""
204-
SELECT "kitchens"."id", json_group_array(CASE WHEN ("kitchenSinks"."id" IS NOT NULL) THEN json_object('id', json_quote("kitchenSinks"."id"), 'kitchenID', json_quote("kitchenSinks"."kitchenID"), 'bool', json(CASE "kitchenSinks"."bool" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'optionalBool', json(CASE "kitchenSinks"."optionalBool" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'string', json_quote("kitchenSinks"."string"), 'optionalString', json_quote("kitchenSinks"."optionalString"), 'int', json_quote("kitchenSinks"."int"), 'optionalInt', json_quote("kitchenSinks"."optionalInt"), 'double', json_quote("kitchenSinks"."double"), 'optionalDouble', json_quote("kitchenSinks"."optionalDouble"), 'rawRepresentable', json_quote("kitchenSinks"."rawRepresentable"), 'optionalRawRepresentable', json_quote("kitchenSinks"."optionalRawRepresentable"), 'iso8601Date', json_quote("kitchenSinks"."iso8601Date"), 'optionalISO8601Date', json_quote("kitchenSinks"."optionalISO8601Date"), 'unixTimeDate', datetime("kitchenSinks"."unixTimeDate", 'unixepoch'), 'optionalUnixTimeDate', datetime("kitchenSinks"."optionalUnixTimeDate", 'unixepoch'), 'julianDayDate', datetime("kitchenSinks"."julianDayDate", 'julianday'), 'optionalJulianDayDate', datetime("kitchenSinks"."optionalJulianDayDate", 'julianday'), 'jsonArray', json("kitchenSinks"."jsonArray"), 'optionalJSONArray', json("kitchenSinks"."optionalJSONArray")) END)
214+
SELECT "kitchens"."id", json_group_array(CASE WHEN ("kitchenSinks"."id" IS NOT NULL) THEN json_object('id', json_quote("kitchenSinks"."id"), 'kitchenID', json_quote("kitchenSinks"."kitchenID"), 'bool', json(CASE "kitchenSinks"."bool" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'optionalBool', json(CASE "kitchenSinks"."optionalBool" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'string', json_quote("kitchenSinks"."string"), 'optionalString', json_quote("kitchenSinks"."optionalString"), 'int', json_quote("kitchenSinks"."int"), 'optionalInt', json_quote("kitchenSinks"."optionalInt"), 'double', json_quote("kitchenSinks"."double"), 'optionalDouble', json_quote("kitchenSinks"."optionalDouble"), 'rawRepresentable', json_quote("kitchenSinks"."rawRepresentable"), 'optionalRawRepresentable', json_quote("kitchenSinks"."optionalRawRepresentable"), 'iso8601Date', json_quote("kitchenSinks"."iso8601Date"), 'optionalISO8601Date', json_quote("kitchenSinks"."optionalISO8601Date"), 'unixTimeDate', datetime("kitchenSinks"."unixTimeDate", 'unixepoch'), 'optionalUnixTimeDate', datetime("kitchenSinks"."optionalUnixTimeDate", 'unixepoch'), 'julianDayDate', datetime("kitchenSinks"."julianDayDate", 'julianday'), 'optionalJulianDayDate', datetime("kitchenSinks"."optionalJulianDayDate", 'julianday'), 'jsonArray', json("kitchenSinks"."jsonArray"), 'optionalJSONArray', json("kitchenSinks"."optionalJSONArray"), 'jsonArrayOfDates', json("kitchenSinks"."jsonArrayOfDates")) END)
205215
FROM "kitchens"
206216
FULL JOIN "kitchenSinks" ON ("kitchens"."id" IS "kitchenSinks"."kitchenID")
207217
"""
208-
} results: {
218+
}results: {
209219
"""
210220
┌────────────────┬────────────────────────────────────────────────────────────┐
211221
│ Kitchen(id: 1) │ [ │
@@ -232,7 +242,10 @@ extension SnapshotTests {
232242
│ │ [0]: "Hello", │
233243
│ │ [1]: "world"
234244
│ │ ], │
235-
│ │ optionalJSONArray: nil │
245+
│ │ optionalJSONArray: nil, │
246+
│ │ jsonArrayOfDates: [ │
247+
│ │ [0]: Date(2040-02-14T23:31:30.000Z) │
248+
│ │ ] │
236249
│ │ ), │
237250
│ │ [1]: KitchenSink( │
238251
│ │ id: 3, │
@@ -260,6 +273,9 @@ extension SnapshotTests {
260273
│ │ optionalJSONArray: [ │
261274
│ │ [0]: "Goodnight", │
262275
│ │ [1]: "moon"
276+
│ │ ], │
277+
│ │ jsonArrayOfDates: [ │
278+
│ │ [0]: Date(2040-02-14T23:31:30.000Z) │
263279
│ │ ] │
264280
│ │ ), │
265281
│ │ [2]: KitchenSink( │
@@ -282,7 +298,8 @@ extension SnapshotTests {
282298
│ │ julianDayDate: Date(2014-05-11T12:00:00.000Z), │
283299
│ │ optionalJulianDayDate: nil, │
284300
│ │ jsonArray: [], │
285-
│ │ optionalJSONArray: nil │
301+
│ │ optionalJSONArray: nil, │
302+
│ │ jsonArrayOfDates: [] │
286303
│ │ ) │
287304
│ │ ] │
288305
└────────────────┴────────────────────────────────────────────────────────────┘
@@ -329,4 +346,6 @@ private struct KitchenSink: Codable {
329346
var jsonArray: [String]
330347
@Column(as: [String].JSONRepresentation?.self)
331348
var optionalJSONArray: [String]?
349+
@Column(as: [Date].JSONRepresentation.self)
350+
var jsonArrayOfDates: [Date]
332351
}

0 commit comments

Comments
 (0)