DungeonDev
DungeonDev

Reputation: 1226

Invalid JSON while parsing \n (quoted) string

I have a problem with a Codable parsing... that's my example code:

class Test: Codable {
      let resultCount: Int?
      let quote: String?
}

 var json =  """
{
    "resultCount" : 42,
    "quote" : "My real quote"
}
""".data(using: .utf8)!

 var decoder = JSONDecoder()
 let testDecoded = try! decoder.decode(Test.self, from: json)

Here everything works as expected and the Test object is created.

Now my back end sends me the quote string with a quote in the middle... in this form (please note \"real\"):

class Test: Codable {
      let resultCount: Int?
      let quote: String?
}

 var json =  """
{
    "resultCount" : 42,
    "quote" : "My \"real\" quote"
}
""".data(using: .utf8)!

 var decoder = JSONDecoder()
 let testDecoded = try! decoder.decode(Test.self, from: json)

In this second case the decoder fails to create the object... and that's my error message:

dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "No string key for value in object around character 4." UserInfo={NSDebugDescription=No string key for value in object around character 4.})))

Is there a way to solve this issue?

Upvotes: 2

Views: 2358

Answers (1)

Rob
Rob

Reputation: 437482

To include quotation marks in your JSON there have to be actual \ characters before the quotation marks within the string:

{
    "resultCount" : 42,
    "quote" : "My \"real\" quote"
}

To do that in Swift string literal, you need to escape the \. That results in "My \\"real\\" quote" within the Swift multi-line string literal:

let json = """
    {
        "resultCount" : 42,
        "quote" : "My \\"real\\" quote"
    }
    """.data(using: .utf8)!

let decoder = JSONDecoder()
let testDecoded = try! decoder.decode(Test.self, from: json)

However, if dealing with a standard, non-multiline string literal, you need to escape both the backslash and the quotation mark, resulting in even more confusing looking \"My \\\"real\\\" quote\":

let json = "{\"resultCount\": 42, \"quote\" : \"My \\\"real\\\" quote\"}"
    .data(using: .utf8)!

Upvotes: 2

Related Questions