Swift - remove single backslash

I found I was having this same issue when trying to encode my objects to JSON. Depending on if you're using the newer JSONEncoder class to parse your JSON and you're supporting a minimum of iOS 13, you can use the .withoutEscapingSlashes output formatting:

let encoder = JSONEncoder()
encoder.outputFormatting = .withoutEscapingSlashes

try encoder.encode(yourJSONObject)

Please check the below code.

let jsonStr = "[{\"isSelected\":true,\"languageProficiencies\":[{\"isSelected\":true,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"English\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Malay\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Chinese\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Tamil\"}]"
let convertedStr = jsonStr.replacingOccurrences(of: "\\", with: "", options: .literal, range: nil)
print(convertedStr)

You can just replace those backslashes, for example:

let string2 = string1.stringByReplacingOccurrencesOfString("\\", withString: "")

Or, to avoid the confusion over the fact that the backslash within a normal string literal is escaped with yet another backslash, we can use an extended string delimiter of #" and "#:

let string2 = string1.stringByReplacingOccurrencesOfString(#"\"#, withString: "")

But, if possible, you really should fix that API that is returning those backslashes, as that's obviously incorrect. The author of that code was apparently under the mistaken impression that forward slashes must be escaped, but this is not true.

Bottom line, the API should be fixed to not insert these backslashes, but until that's remedied, you can use the above to remove any backslashes that may occur.


In the discussion in the comments below, there seems to be enormous confusion about backslashes in strings. So, let's step back for a second and discuss "string literals". As the documentation says, a string literal is:

You can include predefined String values within your code as string literals. A string literal is a fixed sequence of textual characters surrounded by a pair of double quotes ("").

Note, a string literal is just a representation of a particular fixed sequence of characters in your code. But, this should not be confused with the underlying String object itself. The key difference between a string literal and the underlying String object is that a string literal allows one to use a backslash as an "escape" character, used when representing special characters (or doing string interpolation). As the documentation says:

String literals can include the following special characters:

  • The escaped special characters \0 (null character), \\ (backslash), \t (horizontal tab), \n (line feed), \r (carriage return), \" (double quote) and \' (single quote)
  • An arbitrary Unicode scalar, written as \u{n}, where n is a 1–8 digit hexadecimal number with a value equal to a valid Unicode code point

So, you are correct that in a string literal, as the excerpt you quoted above points out, you cannot have an unescaped backslash. Thus, whenever you want to represent a single backslash in a string literal, you represent that with a \\.

Thus the above stringByReplacingOccurrencesOfString means "look through the string1, find all occurrences of a single backslash, and replace them with an empty string (i.e. remove the backslash)."

Consider:

let string1 = "foo\\bar"

print(string1)                    // this will print "foo\bar"
print(string1.characters.count)   // this will print "7", not "8"

let string2 = string1.stringByReplacingOccurrencesOfString("\\", withString: "")

print(string2)                    // this will print "foobar"
print(string2.characters.count)   // this will print "6"

A little confusingly, if you look at string1 in the "Variables" view of the "Debug" panel or within playground, it will show a string literal representation (i.e. backslashes will appear as "\\"). But don't be confused. When you see \\ in the string literal, there is actually only a single backslash within the actual string. But if you print the value or look at the actual characters, there is only a single backslash in the string, itself.

In short, do not conflate the escaping of the backslash within a string literal (for example, the parameters to stringByReplacingOccurrencesOfString) and the single backslash that exists in the underlying string.