Skip invalid data instead of exiting completely. #41
Conversation
… collection and prefer to deal with default values instead of an empty collection.
@@ -49,7 +49,7 @@ public func Unbox<T: Unboxable>(data: NSData, context: Any? = nil) -> T? { | |||
} | |||
|
|||
/// Unbox binary data into an array of `T`, while optionally using a contextual object | |||
public func Unbox<T: Unboxable>(data: NSData, context: Any? = nil) -> [T]? { | |||
public func Unbox<T: Unboxable>(data: NSData, context: Any? = nil, skipInvalidData: Bool = false) -> [T]? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're never using this new parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, that was a mistake left from previous attempt before going with UnboxOrSkip
instead of overloading other functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think this is the better approach :) See my comment on the PR itself.
Thanks for this PR! 🚀 I think it's a great addition. 👍 However, I think it'd be a lot better if you continued the parameter approach (extending Also, |
Yes I actually toyed with both ways, as an overloaded parameter and using a separate I never liked Let me make the changes and add some unit tests and I'll update the PR. Thanks a mil for the input! |
Awesome! Thank you so much for doing this 👍 |
…aded Unbox with allowInvalidElements parameter in favor over UnboxOrSkip. Added unit tests.
I just updated the PR to include the updates we discussed and it feels better. The only thing I don't like is I was forced to add the I've also added a unit test. I couldn't figure how to reuse your mock data so I just generated dummy JSON and unboxed it. Let me know if you have any thoughts or suggestions from here and I'll be glad to do another iteration on it. Thanks again! |
Ok not sure how you're going to feel about this, but I moved the public API logic into private functions of |
@@ -696,12 +691,64 @@ private extension Unboxer { | |||
|
|||
return unboxed | |||
} | |||
|
|||
/// Unbox a JSON dictionary into a model `T`, while optionally using a contextual object. Throws `UnboxError`. | |||
static func performUnboxingWithDictionary<T: Unboxable>(dictionary: UnboxableDictionary, context: Any? = nil) throws -> T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move this so that it's together with the other static
functions? Also, the documentation can be removed (since it's private), and remove the default value for the context
parameter.
Sorry for the delayed response :) I really like that you moved the API logic into private functions - it makes a lot of sense 👍 Some minor comments on the formatting, otherwise - great stuff! The only place where I think we need to make some changes is the test - instead of having a JSON string there I think it's a lot better to create the dictionaries in code. Let me know if you want me to help you out on any of these parts :) Thank you a lot for all the work you've done so far 🚀 |
Cool, I updated the code based on your comments, except for the testing. Didn't like it either, will take another swing at it.. |
} | ||
|
||
static func performUnboxingWithDictionary<T: Unboxable>(dictionaries: [UnboxableDictionary], context: Any? = nil, allowInvalidElements: Bool = false) throws -> [T] { | ||
if allowInvalidElements { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome 👍
Awesome stuff! Thanks for making those changes! 👍 Now just the testing left then we can merge this one! 😄 |
Having trouble getting the test to work. Here's what I'm trying:
Commenting out the |
..wait think I found something... hang on.. |
Ok there was actually a bug in my code. There were a few more places I had to add |
…dElements = false).
return try Unboxer(dictionary: dictionary, context: context, allowInvalidElements: allowInvalidElements).performUnboxingWithContext(context) | ||
} | ||
|
||
static func performUnboxingWithDictionaryAndContext<T: UnboxableWithContext>(dictionaries: [UnboxableDictionary], context: T.ContextType, allowInvalidElements: Bool = false) throws -> [T] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method name here should reflect that it takes Dictionaries
instead of just Dictionary
Looks much better now! Although I just thought of something - why add the |
You mean as opposed to keeping them in the Or if you mean why keep it in the |
I agree tho, removing that property from |
Yeah, you can put it in
Makes sense? |
Trying to follow but not grasping yet, looking at it more.. |
@basememara Need to go to bed now (It's 00:40 here), but let's catch up tomorrow. Are you on Twitter? Maybe talking about this through IM is going to be easier, for faster turnaround! But I think we are very close to finishing this :) I'm @JohnSundell if you want to catch up on Twitter. |
For sure, no rush. Will let it marinate and give it more thought as well. Thanks for the input again. |
…of global Unboxer property.
hey! cool you were right!! I moved |
return unboxed | ||
} | ||
|
||
func performCustomUnboxingWithClosure<T>(closure: Unboxer -> T?) throws -> T { | ||
func performCustomUnboxingWithClosure<T>(allowInvalidElements: Bool, closure: Unboxer -> T?) throws -> T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameters in this function are placed in the wrong order, since Closure
is part of the signature, it should be the first argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually intentionally swapped them to allow trailing closure syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I get it. But this is not a public API, so you don't really need that convenience. Also, the name of the method should always match the first argument. So unless you have a strong opinion about it - I think they should be switched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, it's just syntax sugar for internals, which we even aren't using since we're passing variables as parameters anyway. I was only thinking in case someone wanted to extend the library and has that available, but didn't feel strongly about it. Method names matching the 1st parameter is a good convention I wasn't thinking about 👍
Starts to look really good! Sorry for the slow replies, I'm traveling at the moment so have limited time to review PRs :/ Put some comments inline, let me know what you think. |
No worries, take your time. We're making great progress and sleeping on it definitely helps 👍 |
…ure/skip-invalid. Updated pull request to add explicit parameter from:
@basememara why don't you merge my branch in yours instead of downloading the code and committing it? This way of joining the code destroys commits history right? |
…ree/feature/skip-invalid. Updated pull request to add explicit parameter from:" This reverts commit 7718228.
Yes I agree. I tried merging, creating pull requests, etc but couldn't get it done. I reverted the change just now. I believe from here you have to create a pull request against my repo, I'll accept it, then I'll place my changes on top. |
Whether using
Unbox
orUnboxOrThrow
, the current implementation nil's the object or returns an empty collection completely if there is a single property on a single object that is invalid. This is necessary when perfect data is needed.However, this pull request adds an option to skip invalid data and move on to the next property or object. This way, the consuming developer can prefer to deal with default values instead of an empty collection or nil object.
Use as:
Also part of discussion #39.