Skip to content

Commit a2ea36c

Browse files
authored
Restore 9.x Firestore Data Codable behavior (#10598)
1 parent 5a4702f commit a2ea36c

File tree

4 files changed

+55
-5
lines changed

4 files changed

+55
-5
lines changed

FirebaseSharedSwift/Sources/third_party/FirebaseDataEncoder/FirebaseDataEncoder.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,12 @@ public class FirebaseDataEncoder {
139139
/// Defer to `Data` for choosing an encoding.
140140
case deferredToData
141141

142-
/// Encoded the `Data` as a Base64-encoded string. This is the default strategy.
142+
/// Encode the `Data` as a Base64-encoded string. This is the default strategy.
143143
case base64
144144

145+
/// Encode the `Data` as an `NSData` blob.
146+
case blob
147+
145148
/// Encode the `Data` as a custom value encoded by the given closure.
146149
///
147150
/// If the closure fails to encode a value into the given encoder, the encoder will encode an empty automatic container in its place.
@@ -874,6 +877,9 @@ extension __JSONEncoder {
874877
case .base64:
875878
return NSString(string: data.base64EncodedString())
876879

880+
case .blob:
881+
return data as NSData
882+
877883
case .custom(let closure):
878884
let depth = self.storage.count
879885
do {
@@ -1092,6 +1098,9 @@ public class FirebaseDataDecoder {
10921098
/// Decode the `Data` from a Base64-encoded string. This is the default strategy.
10931099
case base64
10941100

1101+
/// Decode the `Data` as an `NSData` blob.
1102+
case blob
1103+
10951104
/// Decode the `Data` as a custom value decoded by the given closure.
10961105
case custom((_ decoder: Swift.Decoder) throws -> Data)
10971106
}
@@ -2484,6 +2493,12 @@ extension __JSONDecoder {
24842493

24852494
return data
24862495

2496+
case .blob:
2497+
guard let data = value as? Data else {
2498+
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
2499+
}
2500+
return data
2501+
24872502
case .custom(let closure):
24882503
self.storage.push(container: value)
24892504
defer { self.storage.popContainer() }

FirebaseSharedSwift/Tests/third_party/DataEncoderTests.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,37 @@ class TestFirebaseDataEncoder: XCTestCase {
413413
_testRoundTrip(of: Optional(data), expected: expected)
414414
}
415415

416+
func testEncodingDataBlob() {
417+
let data = Data([0xDE, 0xAD, 0xBE, 0xEF])
418+
419+
_testRoundTrip(of: data,
420+
expected: data,
421+
dataEncodingStrategy: .blob,
422+
dataDecodingStrategy: .blob)
423+
424+
// Optional data should encode the same way.
425+
_testRoundTrip(of: Optional(data),
426+
expected: data,
427+
dataEncodingStrategy: .blob,
428+
dataDecodingStrategy: .blob)
429+
}
430+
431+
func testEncodingData2Blob() {
432+
let string = "abcdef"
433+
let data = string.data(using: .utf8)!
434+
435+
_testRoundTrip(of: data,
436+
expected: data,
437+
dataEncodingStrategy: .blob,
438+
dataDecodingStrategy: .blob)
439+
440+
// Optional data should encode the same way.
441+
_testRoundTrip(of: Optional(data),
442+
expected: data,
443+
dataEncodingStrategy: .blob,
444+
dataDecodingStrategy: .blob)
445+
}
446+
416447
func testEncodingDataCustom() {
417448
// We'll encode a number instead of data.
418449
let encode = { (_ data: Data, _ encoder: Encoder) throws -> Void in

Firestore/Swift/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 10.4.0
2+
- [fixed] Restore 9.x Codable behavior of encoding `Data` types as an `NSData`
3+
blob instead of a String.
4+
15
# 10.0.0
26
- [changed] **Breaking Change:** The `DocumentID` constructor from a
37
`DocumentReference` is now internal; this does not affect instantiating a

Firestore/Swift/Source/Codable/EncoderDecoder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public extension Firestore {
2323
/// The strategy to use in encoding dates. Defaults to `.timestamp`.
2424
public var dateEncodingStrategy: FirebaseDataEncoder.DateEncodingStrategy = .timestamp
2525

26-
/// The strategy to use in encoding binary data. Defaults to `.base64`.
27-
public var dataEncodingStrategy: FirebaseDataEncoder.DataEncodingStrategy = .base64
26+
/// Firestore encodes Data as `NSData` blobs versus the default .base64 strings.
27+
public var dataEncodingStrategy: FirebaseDataEncoder.DataEncodingStrategy = .blob
2828

2929
/// The strategy to use in encoding non-conforming numbers. Defaults to `.throw`.
3030
public var nonConformingFloatEncodingStrategy: FirebaseDataEncoder
@@ -62,8 +62,8 @@ public extension Firestore {
6262
/// The strategy to use in decoding dates. Defaults to `.timestamp`.
6363
public var dateDecodingStrategy: FirebaseDataDecoder.DateDecodingStrategy = .timestamp
6464

65-
/// The strategy to use in decoding binary data. Defaults to `.base64`.
66-
public var dataDecodingStrategy: FirebaseDataDecoder.DataDecodingStrategy = .base64
65+
/// Firestore decodes Data from `NSData` blobs versus the default .base64 strings.
66+
public var dataDecodingStrategy: FirebaseDataDecoder.DataDecodingStrategy = .blob
6767

6868
/// The strategy to use in decoding non-conforming numbers. Defaults to `.throw`.
6969
public var nonConformingFloatDecodingStrategy: FirebaseDataDecoder

0 commit comments

Comments
 (0)