Skip to content

Commit 8b9774a

Browse files
authored
Handle decoding base64-encoded strings as blob data in Codables (#10604)
1 parent a2ea36c commit 8b9774a

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

FirebaseSharedSwift/Sources/third_party/FirebaseDataEncoder/FirebaseDataEncoder.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2494,10 +2494,15 @@ extension __JSONDecoder {
24942494
return data
24952495

24962496
case .blob:
2497-
guard let data = value as? Data else {
2498-
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
2497+
if let data = value as? Data {
2498+
return data
2499+
} else if let string = value as? String, let data = Data(base64Encoded: string) {
2500+
// Support implicit migration of data that was written with .base64 (String type) using
2501+
// Firestore 10.0 through 10.3.
2502+
return data
24992503
}
2500-
return data
2504+
2505+
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
25012506

25022507
case .custom(let closure):
25032508
self.storage.push(container: value)

FirebaseSharedSwift/Tests/third_party/DataEncoderTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,35 @@ class TestFirebaseDataEncoder: XCTestCase {
482482
dataDecodingStrategy: .custom(decode))
483483
}
484484

485+
func testDecodingBase64StringAsBlobData() {
486+
let data = "abcdef".data(using: .utf8)!
487+
let base64String = "YWJjZGVm"
488+
489+
let encoder = FirebaseDataEncoder()
490+
encoder.dataEncodingStrategy = .base64
491+
var payload: Any! = nil
492+
do {
493+
payload = try encoder.encode(data)
494+
} catch {
495+
XCTFail("Failed to encode \(Data.self): \(error)")
496+
}
497+
498+
XCTAssertEqual(
499+
base64String,
500+
payload as? String,
501+
"Encoding did not produce the expected base64-encoded \(String.self)."
502+
)
503+
504+
let decoder = FirebaseDataDecoder()
505+
decoder.dataDecodingStrategy = .blob
506+
do {
507+
let decoded = try decoder.decode(Data.self, from: payload!)
508+
XCTAssertEqual(data, decoded, "Decoding the base64-encoded payload did not produce a \(Data.self).")
509+
} catch {
510+
XCTFail("Failed to decode \(Data.self): \(error)")
511+
}
512+
}
513+
485514
// MARK: - Non-Conforming Floating Point Strategy Tests
486515

487516
func testEncodingNonConformingFloats() {

Firestore/Swift/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# 10.4.0
22
- [fixed] Restore 9.x Codable behavior of encoding `Data` types as an `NSData`
33
blob instead of a String.
4+
- [added] Added support for decoding base64-encoded strings when using the
5+
`blob` `DataEncodingStrategy` for `Codable`s with `Data` types.
46

57
# 10.0.0
68
- [changed] **Breaking Change:** The `DocumentID` constructor from a

0 commit comments

Comments
 (0)