utahiosmac / Marshal

Marshaling the typeless wild west of [String: Any]
MIT License
698 stars 63 forks source link

SIGABRT when accessing dot separated keypath on non-object fileds #133

Open Sega-Zero opened 5 years ago

Sega-Zero commented 5 years ago

This construction

extension NSDictionary: MarshaledObject {
    public func any(for key: KeyType) throws -> Any {
        guard let value: Any = self.value(forKeyPath: key.stringValue) else {
            throw MarshalError.keyNotFound(key: key)
        }

is not really safe to use in case when we try to access a field that is not an object. Say, we have this json:

{
    "contact_id": "123456",
    "type": 0,
    "avatar": "",
    "org": {"name": "name"},
}

And this model:

struct Test: Unmarshaling {
    let identifier: String
    let orgName: String?
    init(object: MarshaledObject) throws {
        self.identifier = try object.value(for: "contact_id")
        self.name = try object.value(for: "org.org_name")
    }
}

Sometimes, by accident, server may return this json:

{
    "contact_id": "123456",
    "type": 0,
    "avatar": "",
    "org": "",
}

In that case I get SIGABRT: marshaldictionary swift 2018-10-26 20-45-39

Right now I have to workaround it by implementing a private struct for org field and map to it first, but it would be better if the code above would just return nil without crashing