Backslashes in Swift String

I am a bit confused by some of Swift's behavior and hoping someone can provide some clarification. This is specifically with how Swift String handles backslashes and decoding to JSON. Imagine I receive a string which has backslashes in it from a server.

One of the servers I'm working with will return JSON where there's a quote inside the string. I have validated the JSON in multiple tools and all seems OK, but I can't seem to decode it in Swift.

Take this example.

struct G : Codable {
  var value : String
}

let noQuoteResponse = """
{"value":"Hello, world"}
"""

let quoteResponse = """
{"value":"He\"llo, world"}
"""

let stringLiteralQuote = #"{"value":"He\"llo, world"}"#

let dec = JSONDecoder()

do {
  let res = try dec.decode(G.self, from: noQuoteResponse.data(using: .utf8)!) //all good

  let res2 = try dec.decode(G.self, from: quoteResponse.data(using: .utf8)!) //fails because of the backslash. I have also tried replacing "\\" with "\\\\" in the string but it doesn't work.

  let res3 = try dec.decode(G.self, from: stringLiteralQuote.data(using: .utf8)!) //all good

  print(res)
} catch {
  print(error)
}

Unfortunately no matter how much I try, I can't seem to decode what used to be pretty easy to do prior.

You have to use

let quoteResponse = """
{"value":"He\\"llo, world"}
"""

Explanation: Without the #...# syntax, a backslash is denoting an escape. So to achieve \" in JSON (to escape the "), you have to type \\" to get the JSON-backslash.

1 Like

Yes, a double backslash would be great. But unfortunately I am receiving the response from a server that I don't control. I have tried to replace the slashes in the string but it always fails.

let quoteResponse = """
{"value":"He\"llo, world"}
"""
    .replacingOccurrences(of: "\\", with: "\\\\", options: .literal)

print(quoteResponse) //{"value":"He"llo, world"} <-- invalid JSON

In this string there is no backslash, only a quote.

If you get the JSON from a server as a string, the string should be OK to parse without manipulation, else the server where you get the JSON from is doing something wrong, and this is hard to correct on your side.

1 Like

Hi Stefan, I am trying to understand. What do you mean there's no backslash? The String the server sends is as seen when I print it. It validates just fine with other JSON validation tools.

The response comes as Data and I convert it to string using UTF8 encoding. Internal quotes are marked as " which is valid JSON.

print(response) // {"value":"He\"llo, world"} The backslash is between the e and ".

Using

let quoteResponse = """
{"value":"He\\"llo, world"}
"""

...

print(quoteResponse)
print(res2)
print(res2.value)

in your code prints

{"value":"He\"llo, world"}
G(value: "He\"llo, world")
He"llo, world

If the response is printed as {"value":"He\"llo, world"}, then it is parsable as JSON, do not try to manipulate it before parsing.

OK I understand. Thanks!

1 Like