Недействительный JSON при разборе строки \ n (заключенная в кавычки)

У меня проблема с синтаксическим анализом Codable ... это мой пример кода:

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)

Здесь все работает как положено, и объект Test создан.

Теперь моя серверная часть отправляет мне строку цитаты с цитатой посередине ... в этой форме (обратите внимание на \ "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)

Во втором случае декодеру не удается создать объект ... и это мое сообщение об ошибке:

данные UserInfo = {NSDebugDescription = Нет строкового ключа для значения в объекте вокруг символа 4.})))

Есть ли способ решить эту проблему?


person DungeonDev    schedule 04.01.2019    source источник
comment
Встроенные кавычки в JSON должны быть экранированы. В строковом литерале это будет "My \\"real\\" quote"   -  person Martin R    schedule 04.01.2019
comment
Вам нужно использовать \\ в строковом литерале, чтобы избежать ". С такой строкой ваш код работает нормально. Ваш бэкэнд отправляет настоящий JSON с экранированными кавычками? Вы должны поместить фактический JSON в файл, чтобы обойти двойное экранирование, которое вам нужно сделать в строковых литералах, и протестировать его, чтобы имитировать бэкэнд.   -  person Dávid Pásztor    schedule 04.01.2019


Ответы (1)


Чтобы включить кавычки в ваш JSON, перед кавычками в строке должны быть фактические \ символы:

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

Чтобы сделать это в строковом литерале Swift, вам нужно экранировать \. Это приводит к "My \\"real\\" quote" в многострочном строковом литерале Swift:

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

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

Однако, если вы имеете дело со стандартным строковым литералом, не состоящим из нескольких строк, вам нужно избегать как обратной косой черты, так и кавычек, что приведет к еще более запутанному виду \"My \\\"real\\\" quote\":

let json = "{\"resultCount\": 42, \"quote\" : \"My \\\"real\\\" quote\"}"
    .data(using: .utf8)!
person Rob    schedule 04.01.2019
comment
Спасибо! ... и спасибо всем остальным. Таким образом, проблема заключалась в строковом литерале, а не в самом JSON из серверной службы (iTunes API использует ту же цитату во многих полях). - person DungeonDev; 04.01.2019