 }
 
 
-public func ==(lhs: JSONPath, rhs: JSONPath) -> Bool {
-    return lhs.components == rhs.components
+//MARK:- Debug Description
+
+extension JSONPath: CustomDebugStringConvertible {
+
+    public var debugDescription: String {
+        var description = ""
+
+        for component in components {
+            switch component {
+            case .Text(let text):
+                description += "['\(text)']"
+                break
+
+            case .Numeric(let number):
+                description += "[\(number)]"
+
+            case .SelfReference:
+                description += "[self]"
+            }
+        }
+
+        return description
+    }
+}
+
+
+extension JSONPath.Component: CustomDebugStringConvertible {
+
+    public var debugDescription: String {
+        switch self {
+        case .Numeric(let i):
+            return "[\(i)]"
+        case .SelfReference:
+            return "[self]"
+        case .Text(let text):
+            return encodeStringAsSubscriptRepresentation(text)
+        }
+    }
+
+    private func encodeStringAsSubscriptRepresentation(text: String) -> String {
+        let mutableText =  NSMutableString(string: text)
+        //Note that the order of the replacements is significant. We must replace '`' first otherwise our replacements will get replaced.
+        mutableText.replaceOccurrencesOfString("`", withString: "``", options: [], range: NSRange(location: 0, length: mutableText.length))
+        mutableText.replaceOccurrencesOfString("'", withString: "`'", options: [], range: NSRange(location: 0, length: mutableText.length))
+
+        return "['\(mutableText)']"
+    }
+}
+
+
+extension JSONPath {
+    //deprecated
+    public static func encodeTextAsSubscriptPathComponent(text: String) -> String {
+        return JSONPath.Component.Text(text).debugDescription
+    }
 }
 
 

    /// A cache of the values of each component of a path. The key is the path and the value is an array of NSNumber, NSString and NSNull which represent .Numeric, .Text and .SelfReference respectively.
    private static let componentsCache = NSCache()

    public init(path: String) throws {
        let components: [Component]

        if let cachedComponents = JSONPath.componentsCache.objectForKey(path) as? [AnyObject] {
            //The cache can't store enums so we have to map back from AnyObject
            components = cachedComponents.map({ object -> Component in
                switch object {
                case is NSNumber:
                    return Component.Numeric(object.longLongValue)

                case is NSString:
                    return Component.Text(object as! String)

                case is NSNull:
                    return Component.SelfReference

                default:
                    fatalError("Unexpected type in component cache.")
                }
            })
        } else {
            components = try JSONPath.componentsInPath(path)

            //We can't store an array of enums in an NSCache so we map to an array of AnyObject.
            let componentsArray = components.map({ component -> AnyObject in
                switch component {
                case .Numeric(let number):
                    return NSNumber(longLong: number)

                case .Text(let text):
                    return NSString(string: text)

                case .SelfReference:
                    return NSNull()
                }
            })
            JSONPath.componentsCache.setObject(componentsArray, forKey: path)
        }

        self.init(components: components)

        }
    }
}
