Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Create method for skipping ParseObject keys #144

Merged
merged 4 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- markdownlint-disable -->
![parse-swift](https://user-images.githubusercontent.com/8621344/204069535-e1882bb0-bbcb-4178-87e6-58fd1bed96d1.png)

<h3 align="center">iOS · macOS · watchOS · tvOS · Linux · Android · Windows</h3>
<h3 align="center">iOS · macOS · watchOS · tvOS · visionOS ·Linux · Android · Windows</h3>

<h4 align="center">
⭐️ ParseSwift was highlighted in <a href="https://iosdevweekly.com/issues/560#start" target="_blank"> issue #560</a> of <a href="https://iosdevweekly.com" target="_blank"> iOS Dev Weekly</a> and discussed in <a href="https://blog.swiftpackageindex.com/posts/swift-package-indexing-episode-5/" target="_blank"> episode 5</a> of <a href="https://swiftpackageindexing.transistor.fm" target="_blank">Swift Package Index Twitter Spaces</a> </h3>
Expand Down
40 changes: 24 additions & 16 deletions Sources/ParseSwift/Coding/ParseEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -435,75 +435,76 @@

// MARK: - KeyedEncodingContainerProtocol Methods
mutating func encodeNil(forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }

Check warning on line 438 in Sources/ParseSwift/Coding/ParseEncoder.swift

View check run for this annotation

Codecov / codecov/patch

Sources/ParseSwift/Coding/ParseEncoder.swift#L438

Added line #L438 was not covered by tests
container[key.stringValue] = NSNull()
}
mutating func encode(_ value: Bool, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Int, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Int8, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Int16, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Int32, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Int64, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: UInt, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: UInt8, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: UInt16, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: UInt32, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: UInt64, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: String, forKey key: Key) throws {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.container[key.stringValue] = self.encoder.box(value)
}
mutating func encode(_ value: Float, forKey key: Key) throws {
// Since the float may be invalid and throw, the coding path needs to contain this key.
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.encoder.codingPath.append(key)
defer { self.encoder.codingPath.removeLast() }
self.container[key.stringValue] = try self.encoder.box(value)
}

mutating func encode(_ value: Double, forKey key: Key) throws {
// Since the double may be invalid and throw, the coding path needs to contain this key.
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }
guard !shouldSkipKey(key) else { return }
self.encoder.codingPath.append(key)
defer { self.encoder.codingPath.removeLast() }
self.container[key.stringValue] = try self.encoder.box(value)
}

mutating func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {
if self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys { return }

guard !shouldSkipKey(key) else { return }

var valueToEncode: Encodable = value
if ((value as? Objectable) != nil)
Expand Down Expand Up @@ -542,6 +543,13 @@
self.container[key.stringValue] = try self.encoder.box(valueToEncode)
}

func shouldSkipKey(_ key: Key) -> Bool {
guard self.encoder.skippedKeys.contains(key.stringValue) && !self.encoder.ignoreSkipKeys else {
return false
}
return true
}

mutating func nestedContainer<NestedKey>(
keyedBy keyType: NestedKey.Type,
forKey key: Key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ import XCTest

class ParseEncoderTests: XCTestCase {
struct GameScore: ParseObject, ParseQueryScorable {
//: These are required by ParseObject
// These are required by ParseObject
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var score: Double?
var originalData: Data?

//: ParseUser property
// ParseUser property
var emailVerified: Bool?

//: Your own properties
// Your own properties
var points: Int

//: a custom initializer
// a custom initializer
init() {
self.points = 5
}
Expand All @@ -34,6 +34,43 @@ class ParseEncoderTests: XCTestCase {
}
}

struct AdditionalTypes: ParseObject {
// These are required by ParseObject
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var score: Double?
var originalData: Data?

// Your own properties
var int8: Int8
var int16: Int16
var int32: Int32
var int64: Int64
var uint: UInt
var uint8: UInt8
var uint16: UInt16
var uint32: UInt32
var uint64: UInt64
var float: Float

// a custom initializer
init() {
self.int8 = 1
self.int16 = 2
self.int32 = 3
self.int64 = 4
self.uint = 5
self.uint8 = 1
self.uint16 = 2
self.uint32 = 3
self.uint64 = 4
self.float = 1.1
}

}

struct Address: Codable {
let street: String
let city: String
Expand Down Expand Up @@ -80,6 +117,25 @@ class ParseEncoderTests: XCTestCase {
XCTAssertEqual(parseDecoded["*"]?["read"], true)
}

func testEncodingAdditionalTypes() throws {
let object = AdditionalTypes()

let encodedJSON = try ParseCoding.parseEncoder().encode(object, skipKeys: .object)
let decodedJSON = try ParseCoding.jsonDecoder().decode([String: AnyCodable].self, from: encodedJSON)
XCTAssertEqual(decodedJSON["int8"]?.value as? NSNumber, NSNumber(value: object.int8))
XCTAssertEqual(decodedJSON["int16"]?.value as? NSNumber, NSNumber(value: object.int16))
XCTAssertEqual(decodedJSON["int32"]?.value as? NSNumber, NSNumber(value: object.int32))
XCTAssertEqual(decodedJSON["int64"]?.value as? NSNumber, NSNumber(value: object.int64))
XCTAssertEqual(decodedJSON["uint"]?.value as? NSNumber, NSNumber(value: object.uint))
XCTAssertEqual(decodedJSON["uint8"]?.value as? NSNumber, NSNumber(value: object.uint8))
XCTAssertEqual(decodedJSON["uint16"]?.value as? NSNumber, NSNumber(value: object.uint16))
XCTAssertEqual(decodedJSON["uint32"]?.value as? NSNumber, NSNumber(value: object.uint32))
XCTAssertEqual(decodedJSON["uint64"]?.value as? NSNumber, NSNumber(value: object.uint64))
#if !os(Linux) && !os(Android) && !os(Windows)
XCTAssertEqual(decodedJSON["float"]?.value as? Double, Double(object.float))
#endif
}

func testSkipKeysDefaultCodingKeys() throws {
var score = GameScore(points: 10)
score.objectId = "yarr"
Expand Down