Search code examples
iosjsonswiftencoderdecoder

'JSONEncoder' / 'JSONDecoder' is ambiguous for type lookup in this context


I am getting following Error

enter image description here

I don't know why I am getting this, How can I resolve it? Please Help!

NOTE: I am using Xcode Version 9.3.1 and Swift4, I had tried to use JSONCodable.JSONEncoder and JSONCodable.JSONDecoder but it won't work.

Here is Code:

import Foundation
import JSONCodable

extension JSONEncoder {
    func encode(_ value: CGAffineTransform, key: String) {
        object[key] = NSValue(cgAffineTransform: value)
    }

    func encode(_ value: CGRect, key: String) {
        object[key] = NSValue(cgRect: value)
    }

    func encode(_ value: CGPoint, key: String) {
        object[key] = NSValue(cgPoint: value)
    }
}

extension JSONDecoder {

    func decode(_ key: String, type: Any.Type) throws -> NSValue {
        guard let value = get(key) else {
            throw JSONDecodableError.missingTypeError(key: key)
        }
        guard let compatible = value as? NSValue else {
            throw JSONDecodableError.incompatibleTypeError(key: key, elementType: type(of: value), expectedType: NSValue.self)
        }
        guard let objcType = String(validatingUTF8: compatible.objCType), objcType.contains("\(type)") else {
            throw JSONDecodableError.incompatibleTypeError(key: key, elementType: type(of: value), expectedType: type)
        }
        return compatible
    }

    func decode(_ key: String) throws -> CGAffineTransform {
        return try decode(key, type: CGAffineTransform.self).cgAffineTransformValue
    }

    func decode(_ key: String) throws -> CGRect {
        return try decode(key, type: CGRect.self).cgRectValue
    }

    func decode(_ key: String) throws -> CGPoint {
        return try decode(key, type: CGPoint.self).cgPointValue
    }
}

Solution

  • The JSONCodable also declares the JSONEncoder/JSONDecoder classes, so the compiler doesn't know which ones you want extend: the standard ones, or the ones from the library.

    Telling to the compiler which class to extend by prefixing the class with the module name, should eliminate the ambiguity.

    import Foundation
    import JSONCodable
    
    extension JSONCodable.JSONEncoder {
        // extension code
    }
    
    extension JSONCodable.JSONDecoder {
        // extension code
    }
    

    However that won't work for this particular library, as the library declares a protocol with the same name (JSONCodable). Thus, you need to explicitly import only the two classes from the module (see this SO post for more details):

    import Foundation
    import class JSONCodable.JSONEncoder
    import class JSONCodable.JSONDecoder
    
    extension JSONCodable.JSONEncoder {
        // your code
    }
    
    extension JSONCodable.JSONDecoder {
        // your code
    }