Marshal icon indicating copy to clipboard operation
Marshal copied to clipboard

Make `MarshalError` more descriptive

Open olejnjak opened this issue 5 years ago • 1 comments

Hi,

I love using Marshal for mapping as it's far more simple and straightforward than other options.

I think that the only pain is that if mapping fails for some reason, it is very complicated to determine where the problem occurred (especially if you have complicated JSON structure with repeating keys). I thought that this could be solved by making MarshalError a bit more descriptive. This would mean that MarshalError would become a struct.

Let's say it would look like this (maybe adding a property to add the payload which failed to map would be also useful).

public struct MarshalError {
    public enum Kind { ... current MarshalError cases }

    public let kind: Kind
    public let objectTypes: [Any.Type]
}

This structure would allow any ValueType to add which type didn't managed to map itself. I've been playing with this idea in playground so this would be the first idea of implementation, but I'm sure it would be possible to wrap it into some function which would make the use of it easier.

I'm open to implementing this change but I'd love to discuss it first - it's a big breaking change and I don't want to make it without any chance to get this merged 🙂.

olejnjak avatar Oct 08 '18 13:10 olejnjak

Wouldn't it be better to add another indirect enum case that will wrap other cases? Something similar to this:

indirect enum MyError: Error, CustomStringConvertible {
    case type1(type: Any.Type)
    case type2(type: Any.Type)
    case wrapping(error: MyError, type: Any.Type)

    var description: String {
        switch self {
        case .type1(let type):
            return "Type1 (type: \(type))"
        case .type2(let type):
            return "Type1 (type: \(type))"
        case let .wrapping(error, type):
            return """
                   Wrapping error for type: \(type). Containing error:
                   \(error)
                   """
        }
    }
}

struct A {
    init() throws {
        throw MyError.type1(type: type(of: self))
    }
}

struct B {
    init() throws {
        do {
            _ = try A()
        } catch let error as MyError {
            throw MyError.wrapping(error: error, type: type(of: self))
        }
    }
}

Sega-Zero avatar Oct 29 '18 22:10 Sega-Zero