Декодировать объект JSON, экранированный в строке - PullRequest
1 голос
/ 18 марта 2020

Я получаю ответ от API (к сожалению, я не могу его изменить), который выглядит примерно так (просто пример):

As bytes => "{\"key\":\"value\"}"

Начальный и завершающие кавычки и экранированные кавычки - все это часть ответа, я решаю его действительно ужасным образом, который выглядит следующим образом:

// (...) Receiving response

guard var responseString = String(bytes: data, encoding: .utf8) else {
    print("Response wasn't just a string, great!") // unfortunately, this never happens
    return
}
responseString = responseString.trimmingCharacters(in: .whitespacesAndNewlines) // make sure it is trimmed
responseString = String(responseString.dropFirst()) // drop the quote at the start
responseString = String(responseString.dropLast()) // drop the quote at the end
responseString = responseString.replacingOccurrences(of: "\\\"", with: "\"")// convert all \" to " (and hope nothing else is escaped <<< this is really bad!!!)
let responseDataToDecode = responseString.data(using: .utf8)!

// (...) decoding with JSONDecoder

Есть ли способ автоматического удаления строки и использования JSON объект, который содержится в нем?

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Если это двойное кодирование, то вам просто нужно двойное декодирование. Если я правильно понимаю, входящие данные выглядят так:

let str = #""{\"key\":\"value\"}""#
// "{\\"key\\":\\"value\\"}"

Первый байт ", второй байт {, третий байт \, четвертый байт ".

Это строка, кодированная JSON. Итак, декодируем это как строку (было время, когда это не работало, потому что это «фрагмент», но в настоящее время он работает нормально, по крайней мере, во всех моих тестах):

let decoder = JSONDecoder()
let string = try! decoder.decode(String.self, from: Data(str.utf8)) // {"key":"value"}

И затем декодируем это как ваш тип ([String:String] только для примера):

let result = try! decoder.decode([String:String].self, from: Data(string.utf8))
// ["key": "value"]

(IMO, этот тип двойного кодирования - это хорошо, кстати, и я не уверен, почему так много комментариев по этому поводу. Сериализация произвольного объекта во многих случаях имеет гораздо больше смысла, чем принуждение схемы работать с произвольной структурой. Пока она четко закодирована, я не вижу здесь никакой проблемы.)

0 голосов
/ 18 марта 2020

Есть первый шаг: вам нужно официальное документированное заявление, каков именно формат ваших данных. Похоже, что кто-то взял некоторые данные, превратил их в JSON данные, интерпретировал данные как строку, а затем преобразовал строку во фрагмент JSON. Нетрудно декодировать фрагмент JSON, получить строку, превратить строку в данные и декодировать эти данные как JSON (начиная с JSONSerialization и .allowFragments, вероятно, единственный раз, когда вы должны использовать .allowFragments в вашей жизни) , Делать это без ругательств сложно.

Но сначала в письменной форме вы хотите, чтобы это был формат. Потому что я бы поспорил, что тот, кто отвечает за этот формат данных, в конечном итоге изменит его, не сообщая вам и не нарушив ваш код.

...