Skip to content

Commit d2ea4b0

Browse files
committed
Handle parsing User when not all required properties are present
1 parent 5a401dc commit d2ea4b0

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

NetworkingInOperations-Example.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
C284F0A620F63CBB009AF6E9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C284F09C20F63CBB009AF6E9 /* Assets.xcassets */; };
2727
C284F0A720F63CBB009AF6E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C284F09E20F63CBB009AF6E9 /* LaunchScreen.storyboard */; };
2828
C284F0A820F63CBB009AF6E9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C284F0A020F63CBB009AF6E9 /* Main.storyboard */; };
29+
C297683F2112F9DD006ED0B7 /* Decodable+Safe.swift in Sources */ = {isa = PBXBuildFile; fileRef = C297683E2112F9DD006ED0B7 /* Decodable+Safe.swift */; };
2930
C29D5E2820F63BD60053D2AB /* NetworkingInOperations_ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C29D5E2720F63BD60053D2AB /* NetworkingInOperations_ExampleTests.swift */; };
3031
/* End PBXBuildFile section */
3132

@@ -60,6 +61,7 @@
6061
C284F09C20F63CBB009AF6E9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6162
C284F09F20F63CBB009AF6E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6263
C284F0A120F63CBB009AF6E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
64+
C297683E2112F9DD006ED0B7 /* Decodable+Safe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Decodable+Safe.swift"; sourceTree = "<group>"; };
6365
C29D5E0D20F63BD50053D2AB /* NetworkingInOperations-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "NetworkingInOperations-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
6466
C29D5E2320F63BD60053D2AB /* NetworkingInOperations-ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NetworkingInOperations-ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
6567
C29D5E2720F63BD60053D2AB /* NetworkingInOperations_ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingInOperations_ExampleTests.swift; sourceTree = "<group>"; };
@@ -128,6 +130,7 @@
128130
3DFEAD2C210DE5B80076C30A /* Extensions */ = {
129131
isa = PBXGroup;
130132
children = (
133+
C297683D2112F9C7006ED0B7 /* Decodable */,
131134
3DFEAD2D210DE5B80076C30A /* NSObject */,
132135
);
133136
path = Extensions;
@@ -257,6 +260,14 @@
257260
path = Storyboards;
258261
sourceTree = "<group>";
259262
};
263+
C297683D2112F9C7006ED0B7 /* Decodable */ = {
264+
isa = PBXGroup;
265+
children = (
266+
C297683E2112F9DD006ED0B7 /* Decodable+Safe.swift */,
267+
);
268+
path = Decodable;
269+
sourceTree = "<group>";
270+
};
260271
C29D5E0420F63BD40053D2AB = {
261272
isa = PBXGroup;
262273
children = (
@@ -406,6 +417,7 @@
406417
3DFEAD37210E1DA10076C30A /* AvatarRetrievalOperation.swift in Sources */,
407418
C21F1CB320F902E100D4138F /* URLRequest+HTTPBody.swift in Sources */,
408419
3DFEAD1F210DE0310076C30A /* QuestionsDataManager.swift in Sources */,
420+
C297683F2112F9DD006ED0B7 /* Decodable+Safe.swift in Sources */,
409421
3DFEAD26210DE14A0076C30A /* QuestionsURLRequestFactory.swift in Sources */,
410422
3DFEAD21210DE0860076C30A /* Question.swift in Sources */,
411423
C21F1CB520F902E100D4138F /* URLRequestFactory.swift in Sources */,

NetworkingInOperations-Example/Data/Managers/Questions/QuestionsDataManager.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,4 @@ class QuestionsDataManager {
2525
operation.completionHandler = completionHandler
2626
queueManager.enqueue(operation)
2727
}
28-
2928
}

NetworkingInOperations-Example/Data/Models/Question.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,34 @@
88

99
import Foundation
1010

11+
private struct DummyCodable: Codable {}
12+
1113
struct QuestionPage: Codable {
14+
1215
let questions: [Question]
1316

17+
// MARK: - CodingKeys
18+
1419
enum CodingKeys: String, CodingKey {
1520
case questions = "items"
1621
}
22+
23+
// MARK: - Init
24+
25+
init(from decoder: Decoder) throws {
26+
let container = try decoder.container(keyedBy: CodingKeys.self)
27+
questions = try container.decodeArrayByIgnoringInvalidElements(Question.self, forKey: .questions)
28+
}
1729
}
1830

1931
struct Question: Codable {
32+
2033
let questionID: Int
2134
let title: String
2235
let user: User
2336

37+
// MARK: - CodingKeys
38+
2439
enum CodingKeys: String, CodingKey {
2540
case questionID = "question_id"
2641
case title = "title"

NetworkingInOperations-Example/Data/Models/User.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct User: Codable, Equatable {
1414
let name: String
1515
let avatarURL: String
1616

17+
// MARK: - CodingKeys
18+
1719
enum CodingKeys: String, CodingKey {
1820
case userID = "user_id"
1921
case name = "display_name"

NetworkingInOperations-Example/Data/Requests/QuestionsURLRequestFactory.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class QuestionsURLRequestFactory: URLRequestFactory {
1313
// MARK: - Retrieval
1414

1515
func requestToRetrieveQuestions() -> URLRequest {
16-
var request = jsonRequest(endPoint: "questions?order=desc&sort=activity&tagged=ios&site=stackoverflow")
16+
var request = jsonRequest(endPoint: "questions?order=desc&sort=activity&tagged=ios&pagesize=100&site=stackoverflow")
1717
request.httpMethod = HTTPRequestMethod.get.rawValue
1818

1919
return request
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Decodable+Safe.swift
3+
// NetworkingInOperations-Example
4+
//
5+
// Created by Boles, William (Developer) on 02/08/2018.
6+
// Copyright © 2018 Boles. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
fileprivate struct DummyCodable: Codable { }
12+
13+
extension UnkeyedDecodingContainer {
14+
15+
public mutating func decodeArrayByIgnoringInvalidElements<T>(_ type: T.Type) throws -> [T] where T : Decodable {
16+
var decodedArray = [T]()
17+
while !isAtEnd {
18+
do {
19+
let item = try decode(T.self)
20+
decodedArray.append(item)
21+
} catch let error {
22+
print("ERROR decoding: \(error)")
23+
_ = try? decode(DummyCodable.self) //Move container onto next item to be decoded
24+
}
25+
}
26+
27+
return decodedArray
28+
}
29+
}
30+
extension KeyedDecodingContainerProtocol {
31+
32+
public func decodeArrayByIgnoringInvalidElements<T>(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T : Decodable {
33+
var unkeyedContainer = try nestedUnkeyedContainer(forKey: key)
34+
35+
return try unkeyedContainer.decodeArrayByIgnoringInvalidElements(type)
36+
}
37+
}

0 commit comments

Comments
 (0)